ummaya 0.2.3 → 0.2.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/README.md +2 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/prompts/manifest.yaml +2 -2
- package/prompts/session_guidance_v1.md +3 -1
- package/prompts/system_v1.md +8 -7
- package/pyproject.toml +2 -7
- package/src/ummaya/context/builder.py +17 -11
- package/src/ummaya/engine/engine.py +27 -7
- package/src/ummaya/engine/query.py +20 -0
- package/src/ummaya/evidence/__init__.py +25 -0
- package/src/ummaya/evidence/__main__.py +7 -0
- package/src/ummaya/evidence/models.py +58 -0
- package/src/ummaya/evidence/runner.py +308 -0
- package/src/ummaya/evidence/task_registry.py +264 -0
- package/src/ummaya/ipc/frame_schema.py +47 -0
- package/src/ummaya/ipc/stdio.py +1287 -54
- package/src/ummaya/llm/client.py +132 -56
- package/src/ummaya/llm/reasoning.py +84 -0
- package/src/ummaya/tools/discovery_bridge.py +17 -1
- package/src/ummaya/tools/executor.py +32 -12
- package/src/ummaya/tools/geocoding/kakao_client.py +1 -2
- package/src/ummaya/tools/kma/apihub_catalog.py +984 -1
- package/src/ummaya/tools/kma/apihub_structured_adapter.py +86 -6
- package/src/ummaya/tools/kma/apihub_url_adapter.py +593 -0
- package/src/ummaya/tools/kma/apihub_url_catalog.py +296 -0
- package/src/ummaya/tools/location_adapters.py +8 -6
- package/src/ummaya/tools/manifest_metadata.py +16 -3
- package/src/ummaya/tools/mvp_surface.py +2 -2
- package/src/ummaya/tools/nmc/emergency_search.py +8 -6
- package/src/ummaya/tools/register_all.py +9 -0
- package/src/ummaya/tools/resolve_location.py +4 -4
- package/src/ummaya/tools/search.py +664 -18
- package/src/ummaya/tools/verified_data_go_kr/_manifest.py +115 -25
- package/src/ummaya/tools/verified_data_go_kr/airkorea_air_quality.py +109 -4
- package/src/ummaya/tools/verified_data_go_kr/nmc_aed_site.py +108 -2
- package/src/ummaya/tools/verified_data_go_kr/pps_bid_public_info.py +174 -9
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_arrival.py +66 -3
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_location.py +12 -2
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_route.py +8 -2
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_route_station.py +114 -0
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_station.py +14 -3
- package/src/ummaya/tools/verify_canonical_map.py +21 -0
- package/tui/package.json +1 -2
- package/tui/src/QueryEngine.ts +4 -0
- package/tui/src/cli/handlers/auth.ts +1 -1
- package/tui/src/cli/handlers/mcp.tsx +3 -3
- package/tui/src/cli/print.ts +69 -18
- package/tui/src/cli/update.ts +13 -13
- package/tui/src/commands/copy/index.ts +1 -1
- package/tui/src/commands/cost/cost.ts +2 -2
- package/tui/src/commands/init-verifiers.ts +5 -5
- package/tui/src/commands/init.ts +30 -30
- package/tui/src/commands/insights.ts +43 -43
- package/tui/src/commands/install-github-app/install-github-app.tsx +2 -2
- package/tui/src/commands/install-github-app/setupGitHubActions.ts +3 -3
- package/tui/src/commands/install.tsx +5 -5
- package/tui/src/commands/mcp/addCommand.ts +5 -5
- package/tui/src/commands/mcp/xaaIdpCommand.ts +2 -2
- package/tui/src/commands/plugin/ManageMarketplaces.tsx +2 -2
- package/tui/src/commands/reasoning/index.ts +13 -0
- package/tui/src/commands/reasoning/reasoning.tsx +177 -0
- package/tui/src/commands/thinkback/thinkback.tsx +3 -3
- package/tui/src/commands.ts +2 -0
- package/tui/src/components/Messages.tsx +2 -1
- package/tui/src/components/Spinner.tsx +2 -2
- package/tui/src/components/design-system/LoadingState.tsx +2 -2
- package/tui/src/ipc/codec.ts +26 -0
- package/tui/src/ipc/frames.generated.ts +398 -303
- package/tui/src/ipc/llmClient.ts +130 -51
- package/tui/src/ipc/llmTypes.ts +16 -1
- package/tui/src/ipc/schema/frame.schema.json +1 -3475
- package/tui/src/main.tsx +3 -0
- package/tui/src/query.ts +467 -2
- package/tui/src/screens/REPL.tsx +3 -3
- package/tui/src/services/api/claude.ts +48 -18
- package/tui/src/services/api/client.ts +33 -12
- package/tui/src/services/api/ummaya.ts +70 -16
- package/tui/src/skills/bundled/stuck.ts +12 -12
- package/tui/src/state/AppStateStore.ts +7 -0
- package/tui/src/tools/AdapterTool/AdapterTool.ts +590 -7
- package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +43 -17
- package/tui/src/tools/LookupPrimitive/prompt.ts +7 -6
- package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +40 -19
- package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +25 -9
- package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +25 -9
- package/tui/src/tools/_shared/citizenUserText.ts +49 -0
- package/tui/src/tools/_shared/directPublicDataGuard.ts +362 -0
- package/tui/src/tools/_shared/kmaAnalysisGuard.ts +197 -0
- package/tui/src/tools/_shared/kmaAviationGuard.ts +70 -0
- package/tui/src/tools/_shared/locationInputRepair.ts +112 -0
- package/tui/src/tools/_shared/nmcAedGuard.ts +234 -0
- package/tui/src/tools/_shared/protectedCheckGuard.ts +207 -0
- package/tui/src/tools/_shared/rootPrimitiveInput.ts +67 -0
- package/tui/src/tools/_shared/textToolCallGuard.ts +91 -0
- package/tui/src/tools/_shared/toolChoiceRepair.ts +866 -0
- package/tui/src/utils/attachments.ts +1 -1
- package/tui/src/utils/kExaoneReasoning.ts +138 -0
- package/tui/src/utils/messages.ts +1 -0
- package/tui/src/utils/multiToolLayout.ts +13 -0
- package/tui/src/utils/processUserInput/processSlashCommand.tsx +2 -2
- package/tui/src/utils/processUserInput/processUserInput.ts +26 -0
- package/tui/src/utils/settings/applySettingsChange.ts +4 -0
- package/tui/src/utils/settings/types.ts +9 -3
- package/tui/src/utils/stats.ts +1 -1
- package/uv.lock +1 -15
- package/assets/copilot-gate-logo.svg +0 -58
- package/assets/govon-logo.svg +0 -40
- package/src/ummaya/eval/__init__.py +0 -5
- package/src/ummaya/eval/retrieval.py +0 -713
- package/tui/src/utils/messageStream.ts +0 -186
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""KMA APIHub non-structured URL operation catalog.
|
|
3
|
+
|
|
4
|
+
These endpoints are official KMA APIHub surfaces, but they are not
|
|
5
|
+
``typ02/openApi`` operations and do not share the structured XML/JSON envelope.
|
|
6
|
+
Keep them in a separate catalog so text, image, and binary response contracts do
|
|
7
|
+
not contaminate the structured OpenAPI wrapper.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import re
|
|
13
|
+
from typing import Literal
|
|
14
|
+
|
|
15
|
+
from pydantic import BaseModel, ConfigDict
|
|
16
|
+
|
|
17
|
+
type KmaApiHubUrlScalar = str | int | float | bool | None
|
|
18
|
+
type KmaApiHubUrlApprovalState = Literal["approved", "approval_pending"]
|
|
19
|
+
type KmaApiHubUrlResponseKind = Literal["text", "image", "binary"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class KmaApiHubUrlParam(BaseModel):
|
|
23
|
+
"""Official request parameter metadata for one APIHub URL operation."""
|
|
24
|
+
|
|
25
|
+
model_config = ConfigDict(frozen=True)
|
|
26
|
+
|
|
27
|
+
name: str
|
|
28
|
+
field_name: str
|
|
29
|
+
required: bool = True
|
|
30
|
+
default: KmaApiHubUrlScalar = None
|
|
31
|
+
value_type: Literal["string", "integer", "number", "boolean"] = "string"
|
|
32
|
+
is_credential: bool = False
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class KmaApiHubUrlOperation(BaseModel):
|
|
36
|
+
"""One official non-structured KMA APIHub URL operation."""
|
|
37
|
+
|
|
38
|
+
model_config = ConfigDict(frozen=True)
|
|
39
|
+
|
|
40
|
+
operation_id: str
|
|
41
|
+
category_seq: int
|
|
42
|
+
category_name_ko: str
|
|
43
|
+
title_ko: str
|
|
44
|
+
endpoint_path: str
|
|
45
|
+
request_params: tuple[KmaApiHubUrlParam, ...]
|
|
46
|
+
response_kind: KmaApiHubUrlResponseKind
|
|
47
|
+
approval_state: KmaApiHubUrlApprovalState = "approval_pending"
|
|
48
|
+
purpose: str
|
|
49
|
+
selection_rule: str
|
|
50
|
+
search_keywords: str
|
|
51
|
+
official_page_url: str
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def tool_id(self) -> str:
|
|
55
|
+
"""Return the stable UMMAYA tool id for this URL operation."""
|
|
56
|
+
return f"kma_apihub_url_{self.operation_id}"
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def non_credential_params(self) -> tuple[KmaApiHubUrlParam, ...]:
|
|
60
|
+
"""Return request parameters that are safe for model/user input."""
|
|
61
|
+
return tuple(param for param in self.request_params if not param.is_credential)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _snake(value: str) -> str:
|
|
65
|
+
value = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", value)
|
|
66
|
+
value = re.sub(r"[^A-Za-z0-9]+", "_", value)
|
|
67
|
+
return value.strip("_").lower()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _value_type(value: KmaApiHubUrlScalar) -> Literal["string", "integer", "number", "boolean"]:
|
|
71
|
+
if isinstance(value, bool):
|
|
72
|
+
return "boolean"
|
|
73
|
+
if isinstance(value, int):
|
|
74
|
+
return "integer"
|
|
75
|
+
if isinstance(value, float):
|
|
76
|
+
return "number"
|
|
77
|
+
return "string"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _param(
|
|
81
|
+
name: str,
|
|
82
|
+
default: KmaApiHubUrlScalar,
|
|
83
|
+
*,
|
|
84
|
+
required: bool = True,
|
|
85
|
+
value_type: Literal["string", "integer", "number", "boolean"] | None = None,
|
|
86
|
+
) -> KmaApiHubUrlParam:
|
|
87
|
+
is_credential = name == "authKey"
|
|
88
|
+
return KmaApiHubUrlParam(
|
|
89
|
+
name=name,
|
|
90
|
+
field_name=_snake(name),
|
|
91
|
+
required=False if is_credential else required,
|
|
92
|
+
default=None if is_credential else default,
|
|
93
|
+
value_type=value_type or _value_type(default),
|
|
94
|
+
is_credential=is_credential,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
KMA_APIHUB_URL_OPERATIONS: tuple[KmaApiHubUrlOperation, ...] = (
|
|
99
|
+
KmaApiHubUrlOperation(
|
|
100
|
+
operation_id="air_metar_decoded",
|
|
101
|
+
category_seq=14,
|
|
102
|
+
category_name_ko="항공기상",
|
|
103
|
+
title_ko="기상청 METAR 해독자료",
|
|
104
|
+
endpoint_path="/api/typ01/url/air_metar_dec.php",
|
|
105
|
+
request_params=(
|
|
106
|
+
_param("tm", None, required=False),
|
|
107
|
+
_param("org", "K"),
|
|
108
|
+
_param("help", 1),
|
|
109
|
+
_param("authKey", None, required=False),
|
|
110
|
+
),
|
|
111
|
+
response_kind="text",
|
|
112
|
+
approval_state="approved",
|
|
113
|
+
purpose=(
|
|
114
|
+
"Fetch official KMA decoded METAR/SPECI aviation weather text. "
|
|
115
|
+
"This is the approved APIHub URL product for the Korean METAR "
|
|
116
|
+
"decoded-data channel."
|
|
117
|
+
),
|
|
118
|
+
selection_rule=(
|
|
119
|
+
"Choose this for METAR decoded-data requests and as the primary "
|
|
120
|
+
"fallback when the structured AmmIwxxmService/getMetar endpoint "
|
|
121
|
+
"returns APIHub APPLICATION_ERROR. It returns KMA decoded text "
|
|
122
|
+
"for the requested time slot, not the structured IWXXM envelope. "
|
|
123
|
+
"The normalized summary identifies known airport stations: station "
|
|
124
|
+
"153 is Gimhae Airport / RKPK, station 110 is Gimpo Airport / RKSS. "
|
|
125
|
+
"Use decoded_records[].safe_weather only for weather values; never "
|
|
126
|
+
"derive values from raw_fields or raw_report. If a wind cardinal "
|
|
127
|
+
"label is needed, use safe_weather.wind.direction_from_cardinal_ko "
|
|
128
|
+
"or direction_from_cardinal_en; do not infer your own label from "
|
|
129
|
+
"degrees."
|
|
130
|
+
),
|
|
131
|
+
search_keywords=(
|
|
132
|
+
"METAR SPECI 해독자료 항공기상전문 공항기상 항공 실황 "
|
|
133
|
+
"비행기 항공편 비행편 운항 이륙 착륙 결항 지연 시정 "
|
|
134
|
+
"air_metar_dec decoded aviation weather flight takeoff landing delay"
|
|
135
|
+
),
|
|
136
|
+
official_page_url="https://apihub.kma.go.kr/apiList.do?seqApi=14",
|
|
137
|
+
),
|
|
138
|
+
KmaApiHubUrlOperation(
|
|
139
|
+
operation_id="air_amos_minute",
|
|
140
|
+
category_seq=14,
|
|
141
|
+
category_name_ko="항공기상",
|
|
142
|
+
title_ko="기상청 AMOS 매분자료 조회",
|
|
143
|
+
endpoint_path="/api/typ01/url/amos.php",
|
|
144
|
+
request_params=(
|
|
145
|
+
_param("tm", None, required=False),
|
|
146
|
+
_param("dtm", 60),
|
|
147
|
+
_param("stn", None),
|
|
148
|
+
_param("help", 1),
|
|
149
|
+
_param("authKey", None, required=False),
|
|
150
|
+
),
|
|
151
|
+
response_kind="text",
|
|
152
|
+
approval_state="approved",
|
|
153
|
+
purpose=(
|
|
154
|
+
"Fetch official AMOS minute observations for supported airports. "
|
|
155
|
+
"AMOS reports runway-area aviation weather such as visibility, RVR, "
|
|
156
|
+
"cloud height, temperature, humidity, pressure, rain, and wind."
|
|
157
|
+
),
|
|
158
|
+
selection_rule=(
|
|
159
|
+
"Choose this for supported-airport runway-area current conditions or "
|
|
160
|
+
"AMOS requests. It covers official AMOS stations such as 110 Gimpo, "
|
|
161
|
+
"but the official APIHub station list does not include Gimhae. "
|
|
162
|
+
"Do not use AMOS for Gimhae; 182 is Jeju, not Gimhae. Use METAR "
|
|
163
|
+
"RKPK for Gimhae aviation weather."
|
|
164
|
+
),
|
|
165
|
+
search_keywords=(
|
|
166
|
+
"AMOS 공항기상관측 매분자료 활주로 기상실황 김포공항 stn110 "
|
|
167
|
+
"비행기 항공편 운항 이륙 착륙 결항 지연 "
|
|
168
|
+
"airport runway minute observation visibility RVR wind flight delay"
|
|
169
|
+
),
|
|
170
|
+
official_page_url=(
|
|
171
|
+
"https://apihub.kma.go.kr/apiList.do?apiMov=%EA%B8%B0%EC%83%81%EC%B2%AD+"
|
|
172
|
+
"AMOS+%EB%A7%A4%EB%B6%84%EC%9E%90%EB%A3%8C+%EC%A1%B0%ED%9A%8C&seqApi=14&seqApiSub=259"
|
|
173
|
+
),
|
|
174
|
+
),
|
|
175
|
+
KmaApiHubUrlOperation(
|
|
176
|
+
operation_id="high_resolution_grid_point",
|
|
177
|
+
category_seq=971,
|
|
178
|
+
category_name_ko="융합기상",
|
|
179
|
+
title_ko="고해상도 격자자료 특정지점 다중요소 조회",
|
|
180
|
+
endpoint_path="/api/typ01/url/sfc_nc_var.php",
|
|
181
|
+
request_params=(
|
|
182
|
+
_param("tm1", None, required=False),
|
|
183
|
+
_param("tm2", None, required=False),
|
|
184
|
+
_param("obs", "ta,td,hm,ws_10m,wd_10m,vs,rn_60m"),
|
|
185
|
+
_param("itv", 10),
|
|
186
|
+
_param("lon", None, value_type="number"),
|
|
187
|
+
_param("lat", None, value_type="number"),
|
|
188
|
+
_param("help", 1),
|
|
189
|
+
_param("authKey", None, required=False),
|
|
190
|
+
),
|
|
191
|
+
response_kind="text",
|
|
192
|
+
approval_state="approved",
|
|
193
|
+
purpose=(
|
|
194
|
+
"Fetch KMA 500m high-resolution analyzed grid values for one "
|
|
195
|
+
"latitude/longitude point. The product applies objective analysis "
|
|
196
|
+
"to KMA and public-agency observations with terrain effects."
|
|
197
|
+
),
|
|
198
|
+
selection_rule=(
|
|
199
|
+
"Choose this when a citizen asks for analyzed weather values at a "
|
|
200
|
+
"coordinate or when point observations are sparse. It complements, "
|
|
201
|
+
"not replaces, official airport METAR/AMOS for flight safety wording. "
|
|
202
|
+
"After locate returns coordinates, call this tool with lat/lon instead "
|
|
203
|
+
"of switching to current-observation or forecast adapters."
|
|
204
|
+
),
|
|
205
|
+
search_keywords=(
|
|
206
|
+
"고해상도 격자자료 분석자료 객관분석 500m 특정지점 다중요소 "
|
|
207
|
+
"기온 습도 풍속 풍향 시정 objective analysis grid point lat lon 융합기상"
|
|
208
|
+
),
|
|
209
|
+
official_page_url=(
|
|
210
|
+
"https://apihub.kma.go.kr/apiList.do?apiMov=1.+%EA%B3%A0%ED%95%B4%EC%83%81%EB%8F%84+"
|
|
211
|
+
"%EA%B2%A9%EC%9E%90%EC%9E%90%EB%A3%8C+%EC%A1%B0%ED%9A%8C%28%ED%95%B4%EC%83%81%EB%8F%84%3A+500m%29"
|
|
212
|
+
"&seqApi=971&seqApiSub=936"
|
|
213
|
+
),
|
|
214
|
+
),
|
|
215
|
+
KmaApiHubUrlOperation(
|
|
216
|
+
operation_id="aws_objective_analysis_grid",
|
|
217
|
+
category_seq=2,
|
|
218
|
+
category_name_ko="지상관측",
|
|
219
|
+
title_ko="AWS 객관분석 격자자료 조회",
|
|
220
|
+
endpoint_path="/api/typ01/cgi-bin/aws/nph-aws_min_obj",
|
|
221
|
+
request_params=(
|
|
222
|
+
_param("obs", "ta"),
|
|
223
|
+
_param("tm", None, required=False),
|
|
224
|
+
_param("obj", "mq"),
|
|
225
|
+
_param("map", "D3"),
|
|
226
|
+
_param("grid", 1),
|
|
227
|
+
_param("stn", 0),
|
|
228
|
+
_param("gov", "", required=False),
|
|
229
|
+
_param("authKey", None, required=False),
|
|
230
|
+
),
|
|
231
|
+
response_kind="text",
|
|
232
|
+
approval_state="approved",
|
|
233
|
+
purpose=(
|
|
234
|
+
"Fetch AWS objective-analysis grid data produced from automatic "
|
|
235
|
+
"weather-station observations."
|
|
236
|
+
),
|
|
237
|
+
selection_rule=(
|
|
238
|
+
"Choose this for AWS objective-analysis grid products, not for a "
|
|
239
|
+
"single airport METAR or ordinary address forecast."
|
|
240
|
+
),
|
|
241
|
+
search_keywords=(
|
|
242
|
+
"AWS 객관분석 격자자료 분석자료 objective analysis grid Multi Quadric Barnes"
|
|
243
|
+
),
|
|
244
|
+
official_page_url=(
|
|
245
|
+
"https://apihub.kma.go.kr/apiList.do?apiMov=AWS%20%EA%B0%9D%EA%B4%80%EB%B6%84%EC%84%9D"
|
|
246
|
+
"&seqApi=2&seqApiSub=248"
|
|
247
|
+
),
|
|
248
|
+
),
|
|
249
|
+
KmaApiHubUrlOperation(
|
|
250
|
+
operation_id="analysis_weather_chart_image",
|
|
251
|
+
category_seq=9,
|
|
252
|
+
category_name_ko="수치모델",
|
|
253
|
+
title_ko="분석일기도 이미지 조회",
|
|
254
|
+
endpoint_path="/api/typ07/afsiwa/iwa/api/iwaImgUrlApi/retRecreateImgUrl.kfrm",
|
|
255
|
+
request_params=(
|
|
256
|
+
_param("analTime", None),
|
|
257
|
+
_param("isTyp", "false"),
|
|
258
|
+
_param("imageType", "png"),
|
|
259
|
+
_param("groupName", "925_default"),
|
|
260
|
+
_param("meta", 1),
|
|
261
|
+
_param("authKey", None, required=False),
|
|
262
|
+
),
|
|
263
|
+
response_kind="image",
|
|
264
|
+
approval_state="approved",
|
|
265
|
+
purpose=("Fetch KMA analyzed weather-chart imagery or metadata for a UTC analysis time."),
|
|
266
|
+
selection_rule=(
|
|
267
|
+
"Choose this for analyzed weather charts or synoptic chart images. "
|
|
268
|
+
"It is not a tabular airport-weather observation source. "
|
|
269
|
+
"For WthrChartInfoService/getSurfaceChart wording, the structured "
|
|
270
|
+
"service is cataloged-disabled after resultCode=99 probes; this URL "
|
|
271
|
+
"image product uses anal_time, not code. Use anal_time, not code. "
|
|
272
|
+
"anal_time is UTC YYYYMMDDHHMM; include minutes and convert from KST "
|
|
273
|
+
"instead of sending a 10-digit local hour."
|
|
274
|
+
),
|
|
275
|
+
search_keywords=(
|
|
276
|
+
"분석일기도 일기도 이미지 수치모델 분석자료 synoptic chart image analTime"
|
|
277
|
+
),
|
|
278
|
+
official_page_url=(
|
|
279
|
+
"https://apihub.kma.go.kr/apiList.do?apiMov=1.+%28%EA%B7%B8%EB%9E%98%ED%94%BD%29+"
|
|
280
|
+
"%EB%B6%84%EC%84%9D%EC%9D%BC%EA%B8%B0%EB%8F%84+%EC%A1%B0%ED%9A%8C&seqApi=9&seqApiSub=285"
|
|
281
|
+
),
|
|
282
|
+
),
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def iter_url_operations() -> tuple[KmaApiHubUrlOperation, ...]:
|
|
287
|
+
"""Return all cataloged non-structured URL operations."""
|
|
288
|
+
return KMA_APIHUB_URL_OPERATIONS
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def get_url_operation_by_id(operation_id: str) -> KmaApiHubUrlOperation:
|
|
292
|
+
"""Return one URL operation by stable operation id."""
|
|
293
|
+
for operation in KMA_APIHUB_URL_OPERATIONS:
|
|
294
|
+
if operation.operation_id == operation_id:
|
|
295
|
+
return operation
|
|
296
|
+
raise KeyError(f"Unknown KMA APIHub URL operation: {operation_id}")
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
"""Locate primitive adapters.
|
|
3
3
|
|
|
4
4
|
Each provider endpoint is exposed as a separate ``GovAPITool`` bound to the
|
|
5
|
-
``locate`` primitive. The
|
|
5
|
+
``locate`` primitive. The model-facing path is the concrete adapter function:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
kakao_keyword_search({"query": "<place>"})
|
|
8
|
+
|
|
9
|
+
The root ``locate({"tool_id": "<adapter>", "params": {...}})`` tool stays as
|
|
10
|
+
a thin envelope for legacy transcripts and compatibility paths.
|
|
8
11
|
|
|
9
12
|
This keeps provider semantics in adapter descriptions and schemas instead of
|
|
10
13
|
pre-processing citizen queries inside the primitive dispatcher.
|
|
@@ -426,7 +429,7 @@ KAKAO_ADDRESS_SEARCH_TOOL = GovAPITool(
|
|
|
426
429
|
"search for bare Korean admin-area wording like '부산 다대1동', '사하구 하단동', "
|
|
427
430
|
"or any query ending in 동/읍/면/구 without a named POI. Returns a bundle containing "
|
|
428
431
|
"address, coordinates, KMA nx/ny when in domain, and Kakao b_code when present. "
|
|
429
|
-
"Call as
|
|
432
|
+
"Call as kakao_address_search({query:'...'})."
|
|
430
433
|
),
|
|
431
434
|
search_hint=(
|
|
432
435
|
"locate 위치 주소 도로명 지번 행정동 법정동 동 읍 면 구 좌표 geocode kakao address "
|
|
@@ -454,8 +457,7 @@ KAKAO_KEYWORD_SEARCH_TOOL = GovAPITool(
|
|
|
454
457
|
"or '강남역'. Do not use for bare administrative districts like '부산 다대1동'; "
|
|
455
458
|
"use kakao_address_search for those. Returns POI name/category, WGS-84 "
|
|
456
459
|
"lat/lon, and KMA nx/ny when in domain. If a downstream adapter needs q0/q1 "
|
|
457
|
-
"region names, follow with
|
|
458
|
-
"params:{lat:<lat>, lon:<lon>}})."
|
|
460
|
+
"region names, follow with kakao_coord_to_region({lat:<lat>, lon:<lon>})."
|
|
459
461
|
),
|
|
460
462
|
search_hint=(
|
|
461
463
|
"locate 위치 장소 키워드 POI 랜드마크 캠퍼스 역 병원 좌표 kakao keyword "
|
|
@@ -481,7 +483,7 @@ KAKAO_COORD_TO_REGION_TOOL = GovAPITool(
|
|
|
481
483
|
"Locate adapter for Kakao coord2regioncode. Use after a coordinate-producing "
|
|
482
484
|
"locate adapter when a downstream public API needs region_1depth_name/q0, "
|
|
483
485
|
"region_2depth_name/q1, or a 10-digit legal/admin code. "
|
|
484
|
-
"Call as
|
|
486
|
+
"Call as kakao_coord_to_region({lat:<lat>, lon:<lon>})."
|
|
485
487
|
),
|
|
486
488
|
search_hint=("locate 지역 시도 시군구 행정동 법정동 q0 q1 coord2region reverse geocode kakao"),
|
|
487
489
|
policy=_provider_policy("Kakao", "https://www.kakao.com/policy/privacy"),
|
|
@@ -43,7 +43,9 @@ _COMMON_FIELD_DESCRIPTIONS: dict[str, str] = {
|
|
|
43
43
|
),
|
|
44
44
|
"city_code": (
|
|
45
45
|
"Official TAGO cityCode identifying the municipality for bus route, arrival, "
|
|
46
|
-
"location, or station queries."
|
|
46
|
+
"location, or station queries. Use the provider's getCtyCodeList contract; "
|
|
47
|
+
"common metropolitan examples from the TAGO city-code list include "
|
|
48
|
+
"Busan=21, Daegu=22, Incheon=23, Gwangju=24, Daejeon=25, and Ulsan=26."
|
|
47
49
|
),
|
|
48
50
|
"route_no": "Bus route number visible to citizens, mapped to the provider routeNo filter.",
|
|
49
51
|
"route_id": "Official provider routeId returned by a prior route lookup.",
|
|
@@ -62,8 +64,19 @@ _COMMON_FIELD_DESCRIPTIONS: dict[str, str] = {
|
|
|
62
64
|
),
|
|
63
65
|
"job_se_code": "Fair Trade Commission job-section code from the public-data contract.",
|
|
64
66
|
"schl_div_cd": "University school-division code from the KCUE public-data contract.",
|
|
65
|
-
"inqry_div":
|
|
66
|
-
|
|
67
|
+
"inqry_div": (
|
|
68
|
+
"Procurement inquiry division code used by the PPS endpoint. For PPS bid "
|
|
69
|
+
"search-condition operations, use 1 for notice-publication datetime and 2 "
|
|
70
|
+
"for bid-opening datetime."
|
|
71
|
+
),
|
|
72
|
+
"bid_ntce_no": "Bid notice number used by PPS detail-style procurement endpoints.",
|
|
73
|
+
"inqry_bgn_dt": "PPS search start datetime in official YYYYMMDDHHMM format.",
|
|
74
|
+
"inqry_end_dt": "PPS search end datetime in official YYYYMMDDHHMM format.",
|
|
75
|
+
"bid_ntce_nm": "PPS bid notice-name keyword; partial Korean notice names are allowed.",
|
|
76
|
+
"ntce_instt_nm": "PPS public notice agency-name filter; partial agency names are allowed.",
|
|
77
|
+
"dminstt_nm": "PPS demand agency-name filter; partial agency names are allowed.",
|
|
78
|
+
"prtcpt_lmt_rgn_nm": "PPS participation-limit region-name filter, such as 부산광역시.",
|
|
79
|
+
"indstryty_nm": "PPS industry or license-name filter, such as 전기공사업.",
|
|
67
80
|
"prdct_clsfc_no_nm": (
|
|
68
81
|
"Product classification number or name search term for the PPS shopping endpoint."
|
|
69
82
|
),
|
|
@@ -71,8 +71,8 @@ class _LookupInputForLLM(BaseModel):
|
|
|
71
71
|
2. The LLM-visible ``find`` tool is fetch-only: pick a ``tool_id``
|
|
72
72
|
from the injected suffix, supply ``params``, get a typed result.
|
|
73
73
|
3. ``LookupSearchInput`` / ``LookupSearchResults`` survive as
|
|
74
|
-
internal API consumed by the auto-inject path
|
|
75
|
-
|
|
74
|
+
internal API consumed by the auto-inject path and deterministic
|
|
75
|
+
retrieval tests; they are NOT exposed to the LLM.
|
|
76
76
|
"""
|
|
77
77
|
|
|
78
78
|
model_config = ConfigDict(extra="forbid")
|
|
@@ -111,8 +111,8 @@ class NmcEmergencySearchInput(BaseModel):
|
|
|
111
111
|
le=90,
|
|
112
112
|
description=(
|
|
113
113
|
"Coordinate-mode latitude in decimal degrees (WGS-84). Required "
|
|
114
|
-
"when mode='coordinate'. Obtain from a coordinate-producing
|
|
115
|
-
"
|
|
114
|
+
"when mode='coordinate'. Obtain from a prior coordinate-producing "
|
|
115
|
+
"locate result; never guess from place names."
|
|
116
116
|
),
|
|
117
117
|
)
|
|
118
118
|
lon: float | None = Field(
|
|
@@ -121,8 +121,8 @@ class NmcEmergencySearchInput(BaseModel):
|
|
|
121
121
|
le=180,
|
|
122
122
|
description=(
|
|
123
123
|
"Coordinate-mode longitude in decimal degrees (WGS-84). Required "
|
|
124
|
-
"when mode='coordinate'. Obtain from a coordinate-producing
|
|
125
|
-
"
|
|
124
|
+
"when mode='coordinate'. Obtain from a prior coordinate-producing "
|
|
125
|
+
"locate result; never guess from place names."
|
|
126
126
|
),
|
|
127
127
|
)
|
|
128
128
|
q0: str | None = Field(
|
|
@@ -785,8 +785,10 @@ NMC_EMERGENCY_SEARCH_TOOL = GovAPITool(
|
|
|
785
785
|
"비인증 시 auth_required."
|
|
786
786
|
),
|
|
787
787
|
self_contained_decl=(
|
|
788
|
-
"ORDERING: turn1 locate
|
|
789
|
-
"turn2 locate
|
|
788
|
+
"ORDERING: turn1 use a coordinate-producing locate adapter, "
|
|
789
|
+
"turn2 use a region-resolving locate adapter, turn3 본 도구. "
|
|
790
|
+
"If the same citizen request also mentions AED/자동심장충격기, call "
|
|
791
|
+
"nmc_aed_site_locate as a separate find adapter; ER data does not answer AED. "
|
|
790
792
|
"응급실 시간은 '24시간 운영', "
|
|
791
793
|
"outpatient_hours_display는 외래진료로만 설명."
|
|
792
794
|
),
|
|
@@ -88,6 +88,9 @@ def register_all_tools(registry: ToolRegistry, executor: ToolExecutor) -> Routin
|
|
|
88
88
|
from ummaya.tools.kma.apihub_structured_adapter import (
|
|
89
89
|
register as reg_kma_apihub_structured,
|
|
90
90
|
)
|
|
91
|
+
from ummaya.tools.kma.apihub_url_adapter import (
|
|
92
|
+
register as reg_kma_apihub_url,
|
|
93
|
+
)
|
|
91
94
|
from ummaya.tools.kma.forecast_fetch import (
|
|
92
95
|
register as reg_kma_forecast_fetch,
|
|
93
96
|
)
|
|
@@ -141,6 +144,12 @@ def register_all_tools(registry: ToolRegistry, executor: ToolExecutor) -> Routin
|
|
|
141
144
|
# adapters above for citizen-facing forecast/current-weather flows.
|
|
142
145
|
reg_kma_apihub_structured(registry, executor)
|
|
143
146
|
|
|
147
|
+
# KMA APIHub non-structured URL families needed for official AMOS and
|
|
148
|
+
# analyzed-data products. These are kept separate from typ02/openApi because
|
|
149
|
+
# their response contracts are text, image, or binary rather than the
|
|
150
|
+
# structured OpenAPI XML/JSON envelope.
|
|
151
|
+
reg_kma_apihub_url(registry, executor)
|
|
152
|
+
|
|
144
153
|
# Phase 2 adapters (spec 029 — NFA 119 + MOHW SSIS, Layer 3 gated stubs)
|
|
145
154
|
reg_nfa(registry, executor) # T014 — NFA EMS statistics (interface-only)
|
|
146
155
|
reg_mohw(registry, executor) # T025 — MOHW welfare eligibility search (real XML handler)
|
|
@@ -5,8 +5,9 @@ Single entry point for converting a natural-language place reference into
|
|
|
5
5
|
structured location data (coordinates, 10-digit 행정동 code, address, POI).
|
|
6
6
|
|
|
7
7
|
Legacy compatibility resolver chain: kakao → juso → sgis.
|
|
8
|
-
New LLM-visible calls should use
|
|
9
|
-
|
|
8
|
+
New LLM-visible calls should use concrete provider adapters from
|
|
9
|
+
``ummaya.tools.location_adapters``. The root ``locate({tool_id, params})``
|
|
10
|
+
shape is retained only for legacy transcripts and compatibility paths.
|
|
10
11
|
|
|
11
12
|
FR-002: Accepts ``query``, ``want``, and optional ``near`` anchor.
|
|
12
13
|
FR-003: Kakao / JUSO / SGIS are exposed as separate locate adapters; this
|
|
@@ -682,8 +683,7 @@ async def resolve_location( # noqa: C901
|
|
|
682
683
|
# Was previously routed through search_address — a structural bug:
|
|
683
684
|
# the address endpoint returns empty for POI queries like
|
|
684
685
|
# "동아대학교", so every want='poi' call ended in not_found and the
|
|
685
|
-
# LLM fell back to fabricated coordinates
|
|
686
|
-
# `specs/integration-verification/donga-univ-poi-bug/`). Routing
|
|
686
|
+
# LLM fell back to fabricated coordinates. Routing
|
|
687
687
|
# through the keyword endpoint is the byte-correct PyKakao mapping
|
|
688
688
|
# for POI queries.
|
|
689
689
|
try:
|