@nomadamas/k-skill 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/bin/k-skill.js +60 -0
- package/package.json +37 -0
- package/skills/assembly-bill-vote-search/instruction.md +111 -0
- package/skills/assembly-bill-vote-search/skill.json +10 -0
- package/skills/biz-health-check/instruction.md +69 -0
- package/skills/biz-health-check/scripts/biz_health_check.py +163 -0
- package/skills/biz-health-check/skill.json +10 -0
- package/skills/bok-ecos-stats/instruction.md +95 -0
- package/skills/bok-ecos-stats/scripts/bok_ecos.py +302 -0
- package/skills/bok-ecos-stats/skill.json +10 -0
- package/skills/building-register-search/instruction.md +69 -0
- package/skills/building-register-search/scripts/building_register.py +309 -0
- package/skills/building-register-search/scripts/building_register_xml.py +32 -0
- package/skills/building-register-search/skill.json +9 -0
- package/skills/bunjang-search/instruction.md +154 -0
- package/skills/bunjang-search/skill.json +10 -0
- package/skills/catchtable-sniper/instruction.md +270 -0
- package/skills/catchtable-sniper/skill.json +9 -0
- package/skills/cheap-gas-nearby/instruction.md +107 -0
- package/skills/cheap-gas-nearby/skill.json +10 -0
- package/skills/corporate-registration-consulting/instruction.md +117 -0
- package/skills/corporate-registration-consulting/scripts/fill_official_hwp.py +106 -0
- package/skills/corporate-registration-consulting/skill.json +8 -0
- package/skills/coupang-product-search/instruction.md +219 -0
- package/skills/coupang-product-search/scripts/coupang_partners_mcp.py +146 -0
- package/skills/coupang-product-search/skill.json +10 -0
- package/skills/court-auction-notice-search/instruction.md +201 -0
- package/skills/court-auction-notice-search/skill.json +9 -0
- package/skills/court-payment-order-assistant/instruction.md +120 -0
- package/skills/court-payment-order-assistant/skill.json +10 -0
- package/skills/d2b-notice-search/instruction.md +117 -0
- package/skills/d2b-notice-search/skill.json +10 -0
- package/skills/daangn-cars-search/instruction.md +91 -0
- package/skills/daangn-cars-search/scripts/daangn_cars.py +72 -0
- package/skills/daangn-cars-search/skill.json +9 -0
- package/skills/daangn-jobs-search/instruction.md +90 -0
- package/skills/daangn-jobs-search/scripts/daangn_jobs.py +98 -0
- package/skills/daangn-jobs-search/skill.json +9 -0
- package/skills/daangn-realty-search/instruction.md +114 -0
- package/skills/daangn-realty-search/scripts/daangn_detail_ld.py +76 -0
- package/skills/daangn-realty-search/scripts/daangn_realty.py +216 -0
- package/skills/daangn-realty-search/scripts/daangn_relay_store.py +174 -0
- package/skills/daangn-realty-search/skill.json +8 -0
- package/skills/daangn-used-goods-search/instruction.md +90 -0
- package/skills/daangn-used-goods-search/scripts/daangn_used_goods.py +80 -0
- package/skills/daangn-used-goods-search/skill.json +9 -0
- package/skills/daishin-report-search/instruction.md +138 -0
- package/skills/daishin-report-search/skill.json +10 -0
- package/skills/daiso-product-search/instruction.md +172 -0
- package/skills/daiso-product-search/skill.json +8 -0
- package/skills/danawa-price-search/instruction.md +183 -0
- package/skills/danawa-price-search/scripts/danawa_search.py +354 -0
- package/skills/danawa-price-search/skill.json +8 -0
- package/skills/delivery-tracking/instruction.md +358 -0
- package/skills/delivery-tracking/skill.json +8 -0
- package/skills/donation-place-search/instruction.md +129 -0
- package/skills/donation-place-search/skill.json +9 -0
- package/skills/emergency-room-beds/instruction.md +82 -0
- package/skills/emergency-room-beds/skill.json +8 -0
- package/skills/ev-charger-nearby/instruction.md +80 -0
- package/skills/ev-charger-nearby/scripts/ev_charger.py +222 -0
- package/skills/ev-charger-nearby/skill.json +10 -0
- package/skills/ev-subsidy-status/instruction.md +165 -0
- package/skills/ev-subsidy-status/skill.json +10 -0
- package/skills/express-bus-booking/instruction.md +207 -0
- package/skills/express-bus-booking/references/kobus-http-flow.md +159 -0
- package/skills/express-bus-booking/scripts/kobus_express_booking.py +243 -0
- package/skills/express-bus-booking/skill.json +8 -0
- package/skills/fine-dust-location/instruction.md +89 -0
- package/skills/fine-dust-location/skill.json +9 -0
- package/skills/flight-ticket-search/instruction.md +237 -0
- package/skills/flight-ticket-search/scripts/flight_ticket_search.py +501 -0
- package/skills/flight-ticket-search/skill.json +9 -0
- package/skills/foresttrip-vacancy/instruction.md +167 -0
- package/skills/foresttrip-vacancy/scripts/run_foresttrip_vacancy.py +549 -0
- package/skills/foresttrip-vacancy/skill.json +10 -0
- package/skills/fsc-corporate-info/instruction.md +57 -0
- package/skills/fsc-corporate-info/scripts/fsc_corporate_info.py +113 -0
- package/skills/fsc-corporate-info/skill.json +10 -0
- package/skills/g2b-order-plan-search/instruction.md +131 -0
- package/skills/g2b-order-plan-search/scripts/g2b_order_plan.py +158 -0
- package/skills/g2b-order-plan-search/skill.json +10 -0
- package/skills/g2b-sanctioned-supplier/instruction.md +61 -0
- package/skills/g2b-sanctioned-supplier/scripts/g2b_sanctioned_supplier.py +114 -0
- package/skills/g2b-sanctioned-supplier/skill.json +10 -0
- package/skills/gangnamunni-clinic-search/instruction.md +113 -0
- package/skills/gangnamunni-clinic-search/skill.json +9 -0
- package/skills/geeknews-search/instruction.md +69 -0
- package/skills/geeknews-search/scripts/geeknews_search.py +296 -0
- package/skills/geeknews-search/skill.json +8 -0
- package/skills/gongsijiga-search/instruction.md +128 -0
- package/skills/gongsijiga-search/skill.json +9 -0
- package/skills/gov-overseas-trip-report/instruction.md +488 -0
- package/skills/gov-overseas-trip-report/scripts/gov_overseas_trip_report.py +1206 -0
- package/skills/gov-overseas-trip-report/skill.json +9 -0
- package/skills/han-river-water-level/instruction.md +83 -0
- package/skills/han-river-water-level/skill.json +10 -0
- package/skills/highway-traffic-status/instruction.md +88 -0
- package/skills/highway-traffic-status/scripts/highway_traffic.py +315 -0
- package/skills/highway-traffic-status/skill.json +11 -0
- package/skills/hipass-receipt/instruction.md +97 -0
- package/skills/hipass-receipt/skill.json +10 -0
- package/skills/hola-poke-yeoksam/instruction.md +247 -0
- package/skills/hola-poke-yeoksam/skill.json +8 -0
- package/skills/household-waste-info/instruction.md +117 -0
- package/skills/household-waste-info/skill.json +10 -0
- package/skills/housing-official-price/instruction.md +177 -0
- package/skills/housing-official-price/skill.json +10 -0
- package/skills/hwp/instruction.md +206 -0
- package/skills/hwp/skill.json +8 -0
- package/skills/intercity-bus-booking/instruction.md +189 -0
- package/skills/intercity-bus-booking/references/tmoney-intercity-http-flow.md +126 -0
- package/skills/intercity-bus-booking/scripts/intercity_bus_search.py +381 -0
- package/skills/intercity-bus-booking/skill.json +8 -0
- package/skills/iros-registry-automation/instruction.md +229 -0
- package/skills/iros-registry-automation/scripts/iros_pdf_summary.py +249 -0
- package/skills/iros-registry-automation/scripts/upstream.pin +1 -0
- package/skills/iros-registry-automation/skill.json +9 -0
- package/skills/job-posting-match/instruction.md +130 -0
- package/skills/job-posting-match/scripts/job_posting_match.py +396 -0
- package/skills/job-posting-match/scripts/test_job_posting_match.py +54 -0
- package/skills/job-posting-match/skill.json +8 -0
- package/skills/jobkorea-talent-search/instruction.md +118 -0
- package/skills/jobkorea-talent-search/scripts/jobkorea_talent_models.py +27 -0
- package/skills/jobkorea-talent-search/scripts/jobkorea_talent_parse.py +186 -0
- package/skills/jobkorea-talent-search/scripts/jobkorea_talent_search.py +94 -0
- package/skills/jobkorea-talent-search/scripts/jobkorea_talent_search_condition.py +136 -0
- package/skills/jobkorea-talent-search/scripts/test_jobkorea_talent_search.py +76 -0
- package/skills/jobkorea-talent-search/skill.json +9 -0
- package/skills/joseon-sillok-search/instruction.md +76 -0
- package/skills/joseon-sillok-search/scripts/sillok_search.py +552 -0
- package/skills/joseon-sillok-search/skill.json +8 -0
- package/skills/k-dart/instruction.md +406 -0
- package/skills/k-dart/skill.json +8 -0
- package/skills/k-schoollunch-menu/instruction.md +109 -0
- package/skills/k-schoollunch-menu/skill.json +9 -0
- package/skills/k-skill-cleaner/instruction.md +80 -0
- package/skills/k-skill-cleaner/scripts/k_skill_cleaner.py +410 -0
- package/skills/k-skill-cleaner/skill.json +8 -0
- package/skills/k-skill-setup/instruction.md +253 -0
- package/skills/k-skill-setup/skill.json +11 -0
- package/skills/kakao-bar-nearby/instruction.md +76 -0
- package/skills/kakao-bar-nearby/skill.json +8 -0
- package/skills/kakao-map/instruction.md +176 -0
- package/skills/kakao-map/skill.json +10 -0
- package/skills/kakaotalk-mac/instruction.md +189 -0
- package/skills/kakaotalk-mac/skill.json +8 -0
- package/skills/kbl-results/instruction.md +89 -0
- package/skills/kbl-results/skill.json +9 -0
- package/skills/kbo-results/instruction.md +82 -0
- package/skills/kbo-results/skill.json +8 -0
- package/skills/keris-academic-search/instruction.md +81 -0
- package/skills/keris-academic-search/scripts/keris_academic.py +210 -0
- package/skills/keris-academic-search/skill.json +10 -0
- package/skills/kleague-results/instruction.md +92 -0
- package/skills/kleague-results/skill.json +8 -0
- package/skills/kopis-performance-search/instruction.md +109 -0
- package/skills/kopis-performance-search/skill.json +10 -0
- package/skills/korea-weather/instruction.md +93 -0
- package/skills/korea-weather/skill.json +10 -0
- package/skills/korean-character-count/instruction.md +87 -0
- package/skills/korean-character-count/scripts/korean_character_count.js +268 -0
- package/skills/korean-character-count/skill.json +8 -0
- package/skills/korean-cinema-search/instruction.md +177 -0
- package/skills/korean-cinema-search/skill.json +8 -0
- package/skills/korean-heritage-search/instruction.md +106 -0
- package/skills/korean-heritage-search/scripts/korean_heritage_search.py +321 -0
- package/skills/korean-heritage-search/skill.json +8 -0
- package/skills/korean-holiday-calendar/instruction.md +97 -0
- package/skills/korean-holiday-calendar/skill.json +9 -0
- package/skills/korean-humanizer/instruction.md +389 -0
- package/skills/korean-humanizer/references/ai-tell-taxonomy.md +147 -0
- package/skills/korean-humanizer/skill.json +8 -0
- package/skills/korean-jangbu-for/instruction.md +133 -0
- package/skills/korean-jangbu-for/scripts/install.sh +237 -0
- package/skills/korean-jangbu-for/scripts/upstream.pin +1 -0
- package/skills/korean-jangbu-for/skill.json +8 -0
- package/skills/korean-law-search/instruction.md +126 -0
- package/skills/korean-law-search/skill.json +10 -0
- package/skills/korean-marathon-schedule/instruction.md +111 -0
- package/skills/korean-marathon-schedule/skill.json +9 -0
- package/skills/korean-middle-korean/instruction.md +79 -0
- package/skills/korean-middle-korean/scripts/korean_middle_korean.js +214 -0
- package/skills/korean-middle-korean/skill.json +8 -0
- package/skills/korean-patent-search/instruction.md +79 -0
- package/skills/korean-patent-search/scripts/patent_search.py +409 -0
- package/skills/korean-patent-search/skill.json +9 -0
- package/skills/korean-privacy-terms/instruction.md +128 -0
- package/skills/korean-privacy-terms/scripts/install.sh +108 -0
- package/skills/korean-privacy-terms/scripts/upstream.pin +1 -0
- package/skills/korean-privacy-terms/skill.json +8 -0
- package/skills/korean-scholarship-search/instruction.md +317 -0
- package/skills/korean-scholarship-search/references/report-format.md +40 -0
- package/skills/korean-scholarship-search/references/school-discovery.md +61 -0
- package/skills/korean-scholarship-search/references/search-clues.md +58 -0
- package/skills/korean-scholarship-search/references/source-patterns.md +67 -0
- package/skills/korean-scholarship-search/scripts/scholarship_filter.py +811 -0
- package/skills/korean-scholarship-search/scripts/test_scholarship_filter.py +224 -0
- package/skills/korean-scholarship-search/scripts/university_search_plan.py +148 -0
- package/skills/korean-scholarship-search/skill.json +8 -0
- package/skills/korean-slang-writing/instruction.md +181 -0
- package/skills/korean-slang-writing/scripts/_slang_http.py +91 -0
- package/skills/korean-slang-writing/scripts/slang_lookup.py +291 -0
- package/skills/korean-slang-writing/scripts/slang_search.py +284 -0
- package/skills/korean-slang-writing/skill.json +8 -0
- package/skills/korean-spell-check/instruction.md +105 -0
- package/skills/korean-spell-check/scripts/korean_spell_check.py +523 -0
- package/skills/korean-spell-check/skill.json +9 -0
- package/skills/korean-stock-search/instruction.md +194 -0
- package/skills/korean-stock-search/skill.json +10 -0
- package/skills/korean-transit-route/instruction.md +113 -0
- package/skills/korean-transit-route/skill.json +10 -0
- package/skills/kosis-stats/instruction.md +232 -0
- package/skills/kosis-stats/references/kosis-openapi-guide.md +171 -0
- package/skills/kosis-stats/scripts/run_kosis_stats.py +896 -0
- package/skills/kosis-stats/skill.json +9 -0
- package/skills/kr-whois-lookup/instruction.md +107 -0
- package/skills/kr-whois-lookup/skill.json +10 -0
- package/skills/kstartup-search/instruction.md +186 -0
- package/skills/kstartup-search/scripts/run_kstartup.py +424 -0
- package/skills/kstartup-search/skill.json +11 -0
- package/skills/ktx-booking/instruction.md +244 -0
- package/skills/ktx-booking/skill.json +10 -0
- package/skills/lck-analytics/instruction.md +192 -0
- package/skills/lck-analytics/scripts/_lib.js +103 -0
- package/skills/lck-analytics/scripts/analyze-live-game.js +52 -0
- package/skills/lck-analytics/scripts/build-match-report.js +44 -0
- package/skills/lck-analytics/scripts/sync-oracle.js +50 -0
- package/skills/lck-analytics/skill.json +9 -0
- package/skills/lh-notice-search/instruction.md +206 -0
- package/skills/lh-notice-search/skill.json +10 -0
- package/skills/library-book-search/instruction.md +139 -0
- package/skills/library-book-search/skill.json +9 -0
- package/skills/local-election-candidate-search/instruction.md +77 -0
- package/skills/local-election-candidate-search/skill.json +8 -0
- package/skills/localdata-business-status/instruction.md +64 -0
- package/skills/localdata-business-status/scripts/localdata_business_status.py +206 -0
- package/skills/localdata-business-status/skill.json +8 -0
- package/skills/lotto-results/instruction.md +80 -0
- package/skills/lotto-results/skill.json +8 -0
- package/skills/lovebug-report/instruction.md +185 -0
- package/skills/lovebug-report/skill.json +9 -0
- package/skills/market-kurly-search/instruction.md +125 -0
- package/skills/market-kurly-search/skill.json +8 -0
- package/skills/mfds-drug-safety/instruction.md +86 -0
- package/skills/mfds-drug-safety/scripts/mfds_drug_safety.py +184 -0
- package/skills/mfds-drug-safety/skill.json +10 -0
- package/skills/mfds-food-safety/instruction.md +126 -0
- package/skills/mfds-food-safety/scripts/mfds_food_safety.py +281 -0
- package/skills/mfds-food-safety/skill.json +10 -0
- package/skills/myrealtrip-search/instruction.md +239 -0
- package/skills/myrealtrip-search/scripts/myrealtrip_mcp.py +194 -0
- package/skills/myrealtrip-search/scripts/test_myrealtrip_mcp.py +99 -0
- package/skills/myrealtrip-search/skill.json +9 -0
- package/skills/naming-house/instruction.md +146 -0
- package/skills/naming-house/skill.json +8 -0
- package/skills/national-pension-workplace/instruction.md +64 -0
- package/skills/national-pension-workplace/scripts/national_pension_workplace.py +113 -0
- package/skills/national-pension-workplace/skill.json +10 -0
- package/skills/naver-ad-performance/instruction.md +108 -0
- package/skills/naver-ad-performance/scripts/naver_ad_performance.py +240 -0
- package/skills/naver-ad-performance/skill.json +9 -0
- package/skills/naver-blog-research/instruction.md +128 -0
- package/skills/naver-blog-research/scripts/_naver_http.py +58 -0
- package/skills/naver-blog-research/scripts/naver_download_images.py +233 -0
- package/skills/naver-blog-research/scripts/naver_read.py +256 -0
- package/skills/naver-blog-research/scripts/naver_search.py +192 -0
- package/skills/naver-blog-research/skill.json +8 -0
- package/skills/naver-news-search/instruction.md +103 -0
- package/skills/naver-news-search/skill.json +10 -0
- package/skills/naver-shopping-search/instruction.md +94 -0
- package/skills/naver-shopping-search/skill.json +11 -0
- package/skills/nhis-care-checkup-search/instruction.md +116 -0
- package/skills/nhis-care-checkup-search/skill.json +10 -0
- package/skills/nts-business-registration/instruction.md +115 -0
- package/skills/nts-business-registration/scripts/nts_business_registration.py +215 -0
- package/skills/nts-business-registration/skill.json +10 -0
- package/skills/nts-tax-delinquency/instruction.md +54 -0
- package/skills/nts-tax-delinquency/scripts/nts_tax_delinquency.py +150 -0
- package/skills/nts-tax-delinquency/skill.json +8 -0
- package/skills/ohou-today-deal/instruction.md +182 -0
- package/skills/ohou-today-deal/scripts/ohou_today_deal.py +369 -0
- package/skills/ohou-today-deal/skill.json +9 -0
- package/skills/olive-young-search/instruction.md +154 -0
- package/skills/olive-young-search/skill.json +8 -0
- package/skills/parking-lot-search/instruction.md +96 -0
- package/skills/parking-lot-search/skill.json +9 -0
- package/skills/popbill/instruction.md +146 -0
- package/skills/popbill/scripts/popbill_cli.py +284 -0
- package/skills/popbill/scripts/popbill_registry.py +54 -0
- package/skills/popbill/scripts/popbill_safety.py +37 -0
- package/skills/popbill/scripts/popbill_templates.py +71 -0
- package/skills/popbill/skill.json +9 -0
- package/skills/public-restroom-nearby/instruction.md +89 -0
- package/skills/public-restroom-nearby/skill.json +9 -0
- package/skills/real-estate-search/instruction.md +172 -0
- package/skills/real-estate-search/skill.json +10 -0
- package/skills/rhwp-advanced/instruction.md +145 -0
- package/skills/rhwp-advanced/skill.json +8 -0
- package/skills/rhwp-edit/instruction.md +153 -0
- package/skills/rhwp-edit/skill.json +8 -0
- package/skills/s2b-notice-search/instruction.md +66 -0
- package/skills/s2b-notice-search/skill.json +9 -0
- package/skills/saju-fortune/instruction.md +177 -0
- package/skills/saju-fortune/skill.json +8 -0
- package/skills/saramin-talent-search/instruction.md +119 -0
- package/skills/saramin-talent-search/skill.json +9 -0
- package/skills/seoul-bike/instruction.md +83 -0
- package/skills/seoul-bike/scripts/seoul_bike.py +247 -0
- package/skills/seoul-bike/skill.json +10 -0
- package/skills/seoul-density/instruction.md +109 -0
- package/skills/seoul-density/scripts/seoul_density.py +271 -0
- package/skills/seoul-density/skill.json +10 -0
- package/skills/seoul-subway-arrival/instruction.md +85 -0
- package/skills/seoul-subway-arrival/skill.json +9 -0
- package/skills/sh-notice-search/instruction.md +150 -0
- package/skills/sh-notice-search/skill.json +9 -0
- package/skills/srt-booking/instruction.md +181 -0
- package/skills/srt-booking/scripts/srt_booking.py +272 -0
- package/skills/srt-booking/scripts/srt_seats.py +156 -0
- package/skills/srt-booking/skill.json +20 -0
- package/skills/subway-lost-property/instruction.md +93 -0
- package/skills/subway-lost-property/scripts/subway_lost_property.py +244 -0
- package/skills/subway-lost-property/skill.json +8 -0
- package/skills/ticket-availability/instruction.md +175 -0
- package/skills/ticket-availability/scripts/ticket_availability.py +430 -0
- package/skills/ticket-availability/skill.json +9 -0
- package/skills/toss-securities/instruction.md +116 -0
- package/skills/toss-securities/skill.json +9 -0
- package/skills/used-car-price-search/instruction.md +109 -0
- package/skills/used-car-price-search/skill.json +8 -0
- package/skills/yebigun-training/instruction.md +177 -0
- package/skills/yebigun-training/skill.json +9 -0
- package/skills/zipcode-search/instruction.md +159 -0
- package/skills/zipcode-search/scripts/zipcode_search.py +150 -0
- package/skills/zipcode-search/skill.json +8 -0
- package/src/assemble.js +134 -0
- package/src/detect.js +18 -0
- package/templates/action-account.md +4 -0
- package/templates/action-booking.md +5 -0
- package/templates/action-commerce.md +5 -0
- package/templates/action-communication.md +5 -0
- package/templates/action-submission.md +5 -0
- package/templates/browser.md +4 -0
- package/templates/core.md +5 -0
- package/templates/hard-boundary.md +3 -0
- package/templates/local.md +2 -0
- package/templates/lookup.md +2 -0
- package/templates/proxy.md +2 -0
- package/templates/vault.md +4 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ktx-booking",
|
|
3
|
+
"description": "Search, reserve, inspect, and cancel KTX or Korail tickets in Korea with the korail2 + pycryptodome Python packages. Use when the user asks for KTX seats, Korail bookings, train changes, reservation status, remaining seat numbers, car-by-car seats, or power-outlet/good-seat tips. 돌쇠에서는 공식 표면을 통한 후속 액션까지 진행한다.",
|
|
4
|
+
"profiles": [
|
|
5
|
+
"vault",
|
|
6
|
+
"browser",
|
|
7
|
+
"action:booking"
|
|
8
|
+
],
|
|
9
|
+
"frontmatter": "name: ktx-booking\ndescription: Search, reserve, inspect, and cancel KTX or Korail tickets in Korea with the korail2 + pycryptodome Python packages. Use when the user asks for KTX seats, Korail bookings, train changes, reservation status, remaining seat numbers, car-by-car seats, or power-outlet/good-seat tips. 돌쇠에서는 공식 표면을 통한 후속 액션까지 진행한다.\nlicense: MIT\nmetadata:\n category: travel\n locale: ko-KR\n phase: v1"
|
|
10
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# LCK Results + Advanced Analysis
|
|
2
|
+
|
|
3
|
+
## What this skill does
|
|
4
|
+
|
|
5
|
+
이 스킬은 LCK 조회/분석 전용이다.
|
|
6
|
+
|
|
7
|
+
- 특정 날짜 LCK 경기 결과 조회
|
|
8
|
+
- 특정 팀 alias 정규화 후 필터링
|
|
9
|
+
- 현재 스플릿 순위 조회
|
|
10
|
+
- 진행 중 경기 live stats 조회
|
|
11
|
+
- live timeline 기반 turning point 분석
|
|
12
|
+
- Oracle's Elixir 스타일 historical row / CSV 기반
|
|
13
|
+
- 팀 파워 레이팅
|
|
14
|
+
- 챔피언 matchup / synergy 분석
|
|
15
|
+
- patch meta 요약
|
|
16
|
+
- 날짜별 match analysis 생성
|
|
17
|
+
|
|
18
|
+
## Origin / attribution
|
|
19
|
+
|
|
20
|
+
이 스킬은 `jerjangmin` 님이 만든 원본 [`lck-analytics` skill pack](https://github.com/jerjangmin/share/tree/main/SKILL/lck-analytics)을 k-skill 저장소 안으로 옮기고, 이 저장소의 npm workspace / Changesets 배포 방식에 맞게 정리한 버전이다.
|
|
21
|
+
|
|
22
|
+
## When to use
|
|
23
|
+
|
|
24
|
+
- "오늘 LCK 경기 결과 알려줘"
|
|
25
|
+
- "2026-04-01 한화 경기 결과랑 순위 보여줘"
|
|
26
|
+
- "지금 T1 경기 킬/골드/오브젝트 요약해줘"
|
|
27
|
+
- "이 경기 turning point가 뭐였어?"
|
|
28
|
+
- "이 밴픽에서 어느 쪽 조합이 더 좋았는지 설명해줘"
|
|
29
|
+
- "현재 패치에서 어떤 챔피언이 메타 픽인지 보여줘"
|
|
30
|
+
- "LCK 팀 파워 레이팅 보여줘"
|
|
31
|
+
|
|
32
|
+
## Prerequisites
|
|
33
|
+
|
|
34
|
+
- Node.js 18+
|
|
35
|
+
- `npm install -g lck-analytics`
|
|
36
|
+
|
|
37
|
+
패키지가 없으면 다른 방법으로 우회하지 말고 먼저 전역 설치를 시도한다.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install -g lck-analytics
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Inputs
|
|
44
|
+
|
|
45
|
+
### 기본 입력
|
|
46
|
+
|
|
47
|
+
- 날짜: `YYYY-MM-DD`
|
|
48
|
+
- 선택 사항: 팀명, 과거 팀명, 한글/영문 약칭 alias
|
|
49
|
+
|
|
50
|
+
### 고급 분석 입력
|
|
51
|
+
|
|
52
|
+
- Oracle's Elixir 스타일 CSV 문자열 또는 row 배열
|
|
53
|
+
- game id / match id
|
|
54
|
+
- live window/details payload 또는 실시간 fetch 권한
|
|
55
|
+
- patch version
|
|
56
|
+
|
|
57
|
+
## Team alias normalization
|
|
58
|
+
|
|
59
|
+
다음 이름들은 같은 canonical team 으로 인식한다.
|
|
60
|
+
|
|
61
|
+
- `DN SOOPers`
|
|
62
|
+
- `DN FREECS`
|
|
63
|
+
- `광동 프릭스`
|
|
64
|
+
- `Afreeca Freecs`
|
|
65
|
+
|
|
66
|
+
추가로 `T1`, `SKT T1`, `담원`, `Dplus KIA`, `브리온`, `한화`, `젠지`, `피어엑스` 등도 alias 정규화를 지원한다.
|
|
67
|
+
|
|
68
|
+
## Official surfaces
|
|
69
|
+
|
|
70
|
+
이 스킬은 Riot 공식 / 공식 웹앱 표면을 우선 사용한다.
|
|
71
|
+
|
|
72
|
+
- 일정/결과: `getSchedule`
|
|
73
|
+
- 토너먼트 목록: `getTournamentsForLeague`
|
|
74
|
+
- 순위: `getStandings`
|
|
75
|
+
- 이벤트 상세: `getEventDetails`
|
|
76
|
+
- 라이브 window: `https://feed.lolesports.com/livestats/v1/window/{gameId}`
|
|
77
|
+
- 라이브 details: `https://feed.lolesports.com/livestats/v1/details/{gameId}`
|
|
78
|
+
|
|
79
|
+
historical 고급 분석은 Oracle's Elixir 스타일 데이터 입력을 사용한다.
|
|
80
|
+
|
|
81
|
+
## Workflow
|
|
82
|
+
|
|
83
|
+
### Included lightweight local pipeline
|
|
84
|
+
|
|
85
|
+
이 k-skill 팩에는 경량 로컬 파일 기반 파이프라인 스크립트가 포함된다.
|
|
86
|
+
|
|
87
|
+
- `scripts/sync-oracle.js`: Oracle-style CSV → historical cache JSON
|
|
88
|
+
- `scripts/build-match-report.js`: 날짜별 match analysis 생성
|
|
89
|
+
- `scripts/analyze-live-game.js`: game analysis 생성
|
|
90
|
+
- 기본 cache 위치: `.openclaw-lck-cache/`
|
|
91
|
+
|
|
92
|
+
### 1. Basic scoreboard / standings query
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
GLOBAL_NPM_ROOT="$(npm root -g)" node --input-type=module - <<'JS'
|
|
96
|
+
import path from "node:path";
|
|
97
|
+
import { pathToFileURL } from "node:url";
|
|
98
|
+
|
|
99
|
+
const entry = pathToFileURL(
|
|
100
|
+
path.join(process.env.GLOBAL_NPM_ROOT, "lck-analytics", "src", "index.js"),
|
|
101
|
+
).href;
|
|
102
|
+
const { getLckSummary } = await import(entry);
|
|
103
|
+
|
|
104
|
+
const summary = await getLckSummary("2026-04-01", {
|
|
105
|
+
team: "한화",
|
|
106
|
+
includeStandings: true,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
110
|
+
JS
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 2. Historical analytics from Oracle-style CSV
|
|
114
|
+
|
|
115
|
+
직접 API를 호출해도 되지만, local skill pipeline에서는 아래 스크립트 사용을 우선 권장한다.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
node ./lck-analytics/scripts/sync-oracle.js \
|
|
119
|
+
--csv ./lck-analytics/samples/oracle-lck-sample.csv
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 3. Match analysis via local pipeline script
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
node ./lck-analytics/scripts/build-match-report.js \
|
|
126
|
+
--date 2026-04-01
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
필요하면 팀 필터도 같이 준다.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
node ./lck-analytics/scripts/build-match-report.js \
|
|
133
|
+
--date 2026-04-01 \
|
|
134
|
+
--team 한화
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 4. Game analysis with turning points via local pipeline script
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
node ./lck-analytics/scripts/analyze-live-game.js \
|
|
141
|
+
--game game-id
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
fixture 기반으로 분석할 때는 `--window`, `--details` 를 같이 줄 수 있다.
|
|
145
|
+
|
|
146
|
+
## Output guidelines
|
|
147
|
+
|
|
148
|
+
사용자에게는 원본 JSON을 길게 그대로 던지지 말고 먼저 아래 순서로 정리한다.
|
|
149
|
+
|
|
150
|
+
### 경기 결과 요청
|
|
151
|
+
|
|
152
|
+
- 경기 시각
|
|
153
|
+
- 팀1 vs 팀2
|
|
154
|
+
- 상태
|
|
155
|
+
- 세트 스코어
|
|
156
|
+
- 요청 팀 경기만 있으면 해당 경기 우선
|
|
157
|
+
- standings 요청이 있으면 현재 순위 같이 표시
|
|
158
|
+
|
|
159
|
+
### 진행 중 경기 요청
|
|
160
|
+
|
|
161
|
+
- 현재 게임 번호
|
|
162
|
+
- 킬 차이
|
|
163
|
+
- 골드 차이
|
|
164
|
+
- 드래곤/바론/타워 차이
|
|
165
|
+
- turning point 1~3개
|
|
166
|
+
|
|
167
|
+
### historical / meta 요청
|
|
168
|
+
|
|
169
|
+
- sample 수를 먼저 표시
|
|
170
|
+
- 팀 파워 레이팅은 상위 팀부터 정렬
|
|
171
|
+
- champion matchup / synergy는 표본 수가 적으면 낮은 확신도로 표시
|
|
172
|
+
- patch meta는 top picks / risers 위주로 짧게 요약
|
|
173
|
+
|
|
174
|
+
## Done when
|
|
175
|
+
|
|
176
|
+
- 날짜 기준 경기 요약이 있다
|
|
177
|
+
- 요청 팀 필터가 적용된다
|
|
178
|
+
- standings 요청이면 현재 순위가 같이 정리된다
|
|
179
|
+
- live 요청이면 현재 게임 요약과 turning point가 있다
|
|
180
|
+
- historical 입력이 있으면 patch meta 또는 power rating까지 설명할 수 있다
|
|
181
|
+
|
|
182
|
+
## Failure modes
|
|
183
|
+
|
|
184
|
+
- Riot 웹앱 API 구조/헤더가 바뀌면 패키지 수정이 필요할 수 있다
|
|
185
|
+
- `LOLESPORTS_API_KEY` public fallback이 회전되면 환경변수 override가 필요할 수 있다
|
|
186
|
+
- historical CSV 컬럼명이 너무 다르면 Oracle-style 정규화 전에 전처리가 필요할 수 있다
|
|
187
|
+
|
|
188
|
+
## Notes
|
|
189
|
+
|
|
190
|
+
- 이 스킬은 조회/분석 전용이다
|
|
191
|
+
- 사용자의 "오늘/어제" 요청은 항상 절대 날짜(`YYYY-MM-DD`)로 변환해서 실행한다
|
|
192
|
+
- 이 저장소에서 `main` 으로 머지되면 Changesets가 Version Packages PR을 만들고, 그 PR이 merge된 뒤 npm publish가 실행된다
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const { pathToFileURL } = require("node:url");
|
|
4
|
+
|
|
5
|
+
async function loadLckResults() {
|
|
6
|
+
const candidates = [];
|
|
7
|
+
const packageNames = ["lck-analytics", "lck-results"];
|
|
8
|
+
|
|
9
|
+
if (process.env.GLOBAL_NPM_ROOT) {
|
|
10
|
+
for (const packageName of packageNames) {
|
|
11
|
+
candidates.push(path.join(process.env.GLOBAL_NPM_ROOT, packageName, "src", "index.js"));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const globalRoot = await detectGlobalNpmRoot();
|
|
17
|
+
for (const packageName of packageNames) {
|
|
18
|
+
candidates.push(path.join(globalRoot, packageName, "src", "index.js"));
|
|
19
|
+
}
|
|
20
|
+
} catch {
|
|
21
|
+
// ignore detection failure and continue to local fallback
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
candidates.push(path.resolve(__dirname, "..", "..", "packages", "lck-analytics", "src", "index.js"));
|
|
25
|
+
|
|
26
|
+
const entryPath = candidates.find((candidate) => fs.existsSync(candidate));
|
|
27
|
+
if (!entryPath) {
|
|
28
|
+
throw new Error("Could not find lck-analytics package. Install it globally with `npm install -g lck-analytics` or run from the k-skill repo.");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return import(pathToFileURL(entryPath).href);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function ensureDir(dirPath) {
|
|
35
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function readJson(filePath, fallback = null) {
|
|
39
|
+
if (!fs.existsSync(filePath)) {
|
|
40
|
+
return fallback;
|
|
41
|
+
}
|
|
42
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function writeJson(filePath, value) {
|
|
46
|
+
ensureDir(path.dirname(filePath));
|
|
47
|
+
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function readText(filePath, fallback = "") {
|
|
51
|
+
if (!fs.existsSync(filePath)) {
|
|
52
|
+
return fallback;
|
|
53
|
+
}
|
|
54
|
+
return fs.readFileSync(filePath, "utf8");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function parseArgs(argv) {
|
|
58
|
+
const args = {};
|
|
59
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
60
|
+
const token = argv[index];
|
|
61
|
+
if (!token.startsWith("--")) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const key = token.slice(2);
|
|
65
|
+
const next = argv[index + 1];
|
|
66
|
+
if (!next || next.startsWith("--")) {
|
|
67
|
+
args[key] = true;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
args[key] = next;
|
|
71
|
+
index += 1;
|
|
72
|
+
}
|
|
73
|
+
return args;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function formatOutput(value) {
|
|
77
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function resolveCachePaths(baseDir) {
|
|
81
|
+
return {
|
|
82
|
+
root: baseDir,
|
|
83
|
+
historical: path.join(baseDir, "historical-analysis.json"),
|
|
84
|
+
live: path.join(baseDir, "live"),
|
|
85
|
+
reports: path.join(baseDir, "reports"),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function detectGlobalNpmRoot() {
|
|
90
|
+
const { execFileSync } = require("node:child_process");
|
|
91
|
+
return execFileSync("npm", ["root", "-g"], { encoding: "utf8" }).trim();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
ensureDir,
|
|
96
|
+
formatOutput,
|
|
97
|
+
loadLckResults,
|
|
98
|
+
parseArgs,
|
|
99
|
+
readJson,
|
|
100
|
+
readText,
|
|
101
|
+
resolveCachePaths,
|
|
102
|
+
writeJson,
|
|
103
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require("node:fs");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
const {
|
|
5
|
+
formatOutput,
|
|
6
|
+
loadLckResults,
|
|
7
|
+
parseArgs,
|
|
8
|
+
readJson,
|
|
9
|
+
resolveCachePaths,
|
|
10
|
+
writeJson,
|
|
11
|
+
} = require("./_lib");
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
const args = parseArgs(process.argv.slice(2));
|
|
15
|
+
const gameId = args.game;
|
|
16
|
+
if (!gameId) {
|
|
17
|
+
throw new Error("--game <gameId> is required");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const cacheDir = path.resolve(args.cache || path.join(process.cwd(), ".openclaw-lck-cache"));
|
|
21
|
+
const paths = resolveCachePaths(cacheDir);
|
|
22
|
+
const historicalWrapper = readJson(paths.historical, { data: {} });
|
|
23
|
+
const pkg = await loadLckResults();
|
|
24
|
+
|
|
25
|
+
const liveWindowPayload = args.window ? JSON.parse(fs.readFileSync(path.resolve(args.window), "utf8")) : undefined;
|
|
26
|
+
const liveDetailsPayload = args.details ? JSON.parse(fs.readFileSync(path.resolve(args.details), "utf8")) : undefined;
|
|
27
|
+
|
|
28
|
+
const analysis = await pkg.getGameAnalysis(gameId, {
|
|
29
|
+
matchId: args.match,
|
|
30
|
+
number: args.number ? Number(args.number) : null,
|
|
31
|
+
state: args.state || undefined,
|
|
32
|
+
historicalDataset: historicalWrapper.data,
|
|
33
|
+
liveWindowPayload,
|
|
34
|
+
liveDetailsPayload,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const reportFile = path.join(paths.reports, `game-${gameId}.json`);
|
|
38
|
+
writeJson(reportFile, analysis);
|
|
39
|
+
|
|
40
|
+
process.stdout.write(formatOutput({
|
|
41
|
+
ok: true,
|
|
42
|
+
reportFile,
|
|
43
|
+
patch: analysis.patch,
|
|
44
|
+
turningPoints: analysis.turningPoints,
|
|
45
|
+
draftEdge: analysis.draft?.overallEdge || null,
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
main().catch((error) => {
|
|
50
|
+
console.error(error.stack || String(error));
|
|
51
|
+
process.exitCode = 1;
|
|
52
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const {
|
|
4
|
+
formatOutput,
|
|
5
|
+
loadLckResults,
|
|
6
|
+
parseArgs,
|
|
7
|
+
readJson,
|
|
8
|
+
resolveCachePaths,
|
|
9
|
+
writeJson,
|
|
10
|
+
} = require("./_lib");
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
const args = parseArgs(process.argv.slice(2));
|
|
14
|
+
const date = args.date;
|
|
15
|
+
if (!date) {
|
|
16
|
+
throw new Error("--date <YYYY-MM-DD> is required");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const cacheDir = path.resolve(args.cache || path.join(process.cwd(), ".openclaw-lck-cache"));
|
|
20
|
+
const paths = resolveCachePaths(cacheDir);
|
|
21
|
+
const historicalWrapper = readJson(paths.historical, { data: {} });
|
|
22
|
+
const pkg = await loadLckResults();
|
|
23
|
+
|
|
24
|
+
const analysis = await pkg.getMatchAnalysis(date, {
|
|
25
|
+
team: args.team || undefined,
|
|
26
|
+
historicalDataset: historicalWrapper.data,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const reportFile = path.join(paths.reports, `match-${date}${args.team ? `-${args.team}` : ""}.json`);
|
|
30
|
+
writeJson(reportFile, analysis);
|
|
31
|
+
|
|
32
|
+
process.stdout.write(formatOutput({
|
|
33
|
+
ok: true,
|
|
34
|
+
reportFile,
|
|
35
|
+
queryDate: analysis.queryDate,
|
|
36
|
+
matchCount: analysis.matches.length,
|
|
37
|
+
teams: analysis.matches.map((match) => `${match.team1?.name} vs ${match.team2?.name}`),
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
main().catch((error) => {
|
|
42
|
+
console.error(error.stack || String(error));
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const {
|
|
4
|
+
formatOutput,
|
|
5
|
+
loadLckResults,
|
|
6
|
+
parseArgs,
|
|
7
|
+
readText,
|
|
8
|
+
resolveCachePaths,
|
|
9
|
+
writeJson,
|
|
10
|
+
} = require("./_lib");
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
const args = parseArgs(process.argv.slice(2));
|
|
14
|
+
const cacheDir = path.resolve(args.cache || path.join(process.cwd(), ".openclaw-lck-cache"));
|
|
15
|
+
const csvPath = args.csv ? path.resolve(args.csv) : path.join(__dirname, "..", "samples", "oracle-lck-sample.csv");
|
|
16
|
+
const league = args.league || "LCK";
|
|
17
|
+
const csvText = readText(csvPath);
|
|
18
|
+
|
|
19
|
+
if (!csvText.trim()) {
|
|
20
|
+
throw new Error(`CSV not found or empty: ${csvPath}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const pkg = await loadLckResults();
|
|
24
|
+
const historical = pkg.buildHistoricalAnalytics(csvText, { league });
|
|
25
|
+
const paths = resolveCachePaths(cacheDir);
|
|
26
|
+
|
|
27
|
+
writeJson(paths.historical, {
|
|
28
|
+
source: {
|
|
29
|
+
type: "oracle-style-csv",
|
|
30
|
+
csvPath,
|
|
31
|
+
league,
|
|
32
|
+
updatedAt: new Date().toISOString(),
|
|
33
|
+
},
|
|
34
|
+
data: historical,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
process.stdout.write(formatOutput({
|
|
38
|
+
ok: true,
|
|
39
|
+
cacheFile: paths.historical,
|
|
40
|
+
teamRatings: historical.teamPowerRatings.length,
|
|
41
|
+
matchupStats: historical.matchupStats.length,
|
|
42
|
+
synergyStats: historical.synergyStats.length,
|
|
43
|
+
patchMeta: historical.patchMeta.length,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
main().catch((error) => {
|
|
48
|
+
console.error(error.stack || String(error));
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lck-analytics",
|
|
3
|
+
"description": "Riot 공식 LoL Esports 데이터와 Oracle's Elixir 스타일 historical 데이터로 LCK 경기 결과, 현재 순위, live turning point, 밴픽 matchup/synergy, patch meta, 팀 파워 레이팅을 조회한다.",
|
|
4
|
+
"profiles": [
|
|
5
|
+
"vault",
|
|
6
|
+
"lookup"
|
|
7
|
+
],
|
|
8
|
+
"frontmatter": "name: lck-analytics\ndescription: Riot 공식 LoL Esports 데이터와 Oracle's Elixir 스타일 historical 데이터로 LCK 경기 결과, 현재 순위, live turning point, 밴픽 matchup/synergy, patch meta, 팀 파워 레이팅을 조회한다.\nlicense: MIT\nmetadata:\n category: sports\n locale: ko-KR\n phase: v1"
|
|
9
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# LH 청약 공고문 조회
|
|
2
|
+
|
|
3
|
+
## What this skill does
|
|
4
|
+
|
|
5
|
+
한국토지주택공사(LH)가 `apply.lh.or.kr` 로 공고하는 **임대주택·분양주택·주거복지(신혼희망타운 등)·토지·상가 공고**를 공공데이터포털(`data.go.kr`)의 공식 LH 공고 Open API로 조회한다. 요청은 `k-skill-proxy` 의 `/v1/lh-notice/*` 라우트로 보내고, 결과는 공고 목록·공고 상세(주택형별 공급 정보)로 정리한다.
|
|
6
|
+
|
|
7
|
+
본 스킬은 사회초년생, 청년, 신혼부부처럼 **LH 공고 존재 자체를 모르는 사용자**가 공고 마감 전에 공고문을 빠르게 찾을 수 있도록 돕는다.
|
|
8
|
+
|
|
9
|
+
## When to use
|
|
10
|
+
|
|
11
|
+
- "LH 영구임대 공고 지금 뭐 올라와 있어?"
|
|
12
|
+
- "신혼희망타운 공고 요즘 나온 거 정리해줘"
|
|
13
|
+
- "부산광역시 LH 임대주택 공고중인 것 보여줘"
|
|
14
|
+
- "전세임대 공고 중 마감 임박한 거 찾아줘"
|
|
15
|
+
- "공고번호 2015122300019828 상세 정보 보여줘"
|
|
16
|
+
- "행복주택 청년 모집 공고 요약해줘"
|
|
17
|
+
|
|
18
|
+
## When not to use
|
|
19
|
+
|
|
20
|
+
- 개별 사용자의 자격 심사, 당첨 예측, 가점 계산
|
|
21
|
+
- 청약 신청 자동화/자동 제출 (본 스킬은 read-only 조회다)
|
|
22
|
+
- 청약통장·주택도시기금 계좌 업무 (해당 범위는 LH 공고와 별개다)
|
|
23
|
+
- SH(서울주택도시공사)·GH(경기주택도시공사)·iH(인천도시공사) 전용 공고 (본 스킬은 LH 공고만 다룬다)
|
|
24
|
+
|
|
25
|
+
## Inputs
|
|
26
|
+
|
|
27
|
+
- `panSs` (또는 `status`): 공고 상태. `공고중`, `접수중`, `접수마감`, `당첨자발표`, `추정공고` 중 하나. 비우면 전체.
|
|
28
|
+
- `uppAisTpCd` (또는 `category`): 주택 대분류. `01`(토지), `05`(분양주택), `06`(임대주택), `13`(주거복지·신혼희망타운), `22`(상가).
|
|
29
|
+
- `aisTpCd`: 세부 분류 코드 (숫자). 예: `09`=영구임대, `10`=행복주택, `17`=전세임대.
|
|
30
|
+
- `cnpCdNm` (또는 `region`): 지역명. 예: `서울특별시`, `부산광역시`, `전국`.
|
|
31
|
+
- `panNm` (또는 `q`, `keyword`): 공고명 부분 검색 키워드. 예: `행복주택`, `청년`, `든든주택`.
|
|
32
|
+
- `panNtStDt` (또는 `startDate`): 공고 게시일 시작. YYYY-MM-DD / YYYYMMDD / YYYY.MM.DD 모두 허용.
|
|
33
|
+
- `clsgDt` (또는 `endDate`): 접수 마감일 종료. 날짜 포맷 동일.
|
|
34
|
+
- `page` (기본 1, 최대 1000), `pageSize` (기본 50, 최대 1000).
|
|
35
|
+
|
|
36
|
+
상세 조회 (`/v1/lh-notice/detail`) 는 `panId`, `ccrCnntSysDsCd`, `splInfTpCd` 세 값 모두 필수다. 이 값은 목록 응답의 `pan_id`, `ccr_cnnt_sys_ds_cd`, `spl_inf_tp_cd` 를 그대로 쓰면 된다.
|
|
37
|
+
|
|
38
|
+
## Prerequisites
|
|
39
|
+
|
|
40
|
+
- 인터넷 연결
|
|
41
|
+
- `curl` (또는 동일한 HTTP 호출이 가능한 도구)
|
|
42
|
+
|
|
43
|
+
사용자에게 필요한 시크릿은 없다. 공공데이터포털 `DATA_GO_KR_API_KEY` 는 `k-skill-proxy` 서버 쪽에만 둔다.
|
|
44
|
+
|
|
45
|
+
## Default path
|
|
46
|
+
|
|
47
|
+
`KSKILL_PROXY_BASE_URL` 환경변수가 있으면 그 값, 없으면 기본 `https://k-skill-proxy.nomadamas.org` 를 사용한다.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
BASE="${KSKILL_PROXY_BASE_URL:-https://k-skill-proxy.nomadamas.org}"
|
|
51
|
+
BASE="${BASE%/}"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Supported endpoints
|
|
55
|
+
|
|
56
|
+
### 공고 목록 조회
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
GET /v1/lh-notice/search
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
필터는 선택사항이다. 필터 없이 호출하면 최근 공고를 상태 무관하게 최대 50건 돌려준다. 마감 임박한 공고만 보고 싶다면 `panSs=공고중` 과 `clsgDt` 로 구간을 좁힌다.
|
|
63
|
+
|
|
64
|
+
### 공고 상세 조회
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
GET /v1/lh-notice/detail?panId={공고ID}&ccrCnntSysDsCd={연계시스템코드}&splInfTpCd={공급정보유형코드}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
상세 응답은 `notice`(공고 요약) + `supply_infos`(주택형/필지/상가호 별 공급 정보 배열) 를 돌려준다.
|
|
71
|
+
|
|
72
|
+
## Example requests
|
|
73
|
+
|
|
74
|
+
### 목록 — 부산 영구임대 공고중
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
curl -fsS --get "${BASE}/v1/lh-notice/search" \
|
|
78
|
+
--data-urlencode 'panSs=공고중' \
|
|
79
|
+
--data-urlencode 'uppAisTpCd=06' \
|
|
80
|
+
--data-urlencode 'cnpCdNm=부산광역시' \
|
|
81
|
+
--data-urlencode 'pageSize=20'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 목록 — 키워드 "행복주택" 으로 접수중
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
curl -fsS --get "${BASE}/v1/lh-notice/search" \
|
|
88
|
+
--data-urlencode 'q=행복주택' \
|
|
89
|
+
--data-urlencode 'status=접수중'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 상세 — 특정 공고
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
curl -fsS --get "${BASE}/v1/lh-notice/detail" \
|
|
96
|
+
--data-urlencode 'panId=2015122300019828' \
|
|
97
|
+
--data-urlencode 'ccrCnntSysDsCd=03' \
|
|
98
|
+
--data-urlencode 'splInfTpCd=051'
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Response shape
|
|
102
|
+
|
|
103
|
+
### 목록 응답
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"items": [
|
|
108
|
+
{
|
|
109
|
+
"pan_id": "2015122300019828",
|
|
110
|
+
"pan_nm": "2026년 상반기 부산광역시 영구임대주택 예비입주자 모집 공고",
|
|
111
|
+
"upp_ais_tp_cd": "06",
|
|
112
|
+
"ais_tp_cd": "09",
|
|
113
|
+
"ais_tp_cd_nm": "영구임대",
|
|
114
|
+
"cnp_cd_nm": "부산광역시",
|
|
115
|
+
"pan_ss": "공고중",
|
|
116
|
+
"pan_dt": "2026-04-21",
|
|
117
|
+
"clsg_dt": "2026-05-06",
|
|
118
|
+
"rcrit_pblanc_dt": null,
|
|
119
|
+
"spl_inf_tp_cd": "051",
|
|
120
|
+
"ccr_cnnt_sys_ds_cd": "03",
|
|
121
|
+
"detail_url": "https://apply.lh.or.kr/lhapply/apply/wt/wrtanc/selectWrtancInfo.do?panId=2015122300019828&..."
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
"summary": {
|
|
125
|
+
"page": 1,
|
|
126
|
+
"page_size": 20,
|
|
127
|
+
"returned_count": 1,
|
|
128
|
+
"total_count": 1
|
|
129
|
+
},
|
|
130
|
+
"query": {
|
|
131
|
+
"pan_ss": "공고중",
|
|
132
|
+
"upp_ais_tp_cd": "06",
|
|
133
|
+
"cnp_cd_nm": "부산광역시"
|
|
134
|
+
},
|
|
135
|
+
"proxy": {
|
|
136
|
+
"name": "k-skill-proxy",
|
|
137
|
+
"cache": { "hit": false, "ttl_ms": 300000 }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 상세 응답
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"notice": {
|
|
147
|
+
"pan_id": "2015122300019828",
|
|
148
|
+
"pan_nm": "2026년 상반기 부산광역시 영구임대주택 예비입주자 모집 공고",
|
|
149
|
+
"ais_tp_cd_nm": "영구임대",
|
|
150
|
+
"...": "목록 응답과 동일한 필드"
|
|
151
|
+
},
|
|
152
|
+
"supply_infos": [
|
|
153
|
+
{ "HOUSE_TY": "영구임대 29㎡", "SPL_CNT": "120" },
|
|
154
|
+
{ "HOUSE_TY": "영구임대 39㎡", "SPL_CNT": "80" }
|
|
155
|
+
],
|
|
156
|
+
"query": {
|
|
157
|
+
"pan_id": "2015122300019828",
|
|
158
|
+
"ccr_cnnt_sys_ds_cd": "03",
|
|
159
|
+
"spl_inf_tp_cd": "051"
|
|
160
|
+
},
|
|
161
|
+
"proxy": { "...": "..." }
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Response policy
|
|
166
|
+
|
|
167
|
+
- 공식 LH 공고(`apply.lh.or.kr`) 정보만 사용한다. 커뮤니티 요약, 블로그 후기, 사설 부동산 정보는 섞지 않는다.
|
|
168
|
+
- **마감 여부는 KST 기준 현재 날짜와 `clsg_dt` 를 비교해 판정**한다. 오늘 = 마감일이면 "오늘 마감"으로 표기한다.
|
|
169
|
+
- 상세 응답의 `detail_url` 을 항상 함께 보여 준다. 사용자는 공고문 원본으로 바로 접근할 수 있어야 한다.
|
|
170
|
+
- 공고번호(`pan_id`) 를 숨기지 말고 요약에 포함한다. 이후 상세 조회에 그대로 쓴다.
|
|
171
|
+
- **본 스킬은 SH·GH·iH 공고를 포함하지 않는다.** 사용자가 서울시·경기도·인천시 공사 공고를 찾으면 본 스킬로는 못 찾는다는 점을 분명히 말한다.
|
|
172
|
+
|
|
173
|
+
## Keep the answer compact
|
|
174
|
+
|
|
175
|
+
사용자에게 돌려줄 때는 이렇게 압축한다.
|
|
176
|
+
|
|
177
|
+
- 필터 요약: 지역 + 공고 유형 + 상태
|
|
178
|
+
- 결과 건수 (`summary.total_count` 와 `returned_count`)
|
|
179
|
+
- 상위 3-5건 대표 공고: 공고명, 지역, 공고일, 마감일, 상태, 링크
|
|
180
|
+
- 마감 임박(D-3 이하) 공고는 별도로 강조
|
|
181
|
+
- 상세 조회 제안: "공고번호 X 상세 보고 싶으면 `lh-notice/detail` 로 조회"
|
|
182
|
+
|
|
183
|
+
## Failure modes
|
|
184
|
+
|
|
185
|
+
- 필터 값이 잘못되면 `400 bad_request` 가 돌아온다. 오류 메시지를 그대로 노출해 사용자가 교정하게 한다.
|
|
186
|
+
- 프록시 서버에 `DATA_GO_KR_API_KEY` 가 없으면 `503 upstream_not_configured` 가 돌아온다.
|
|
187
|
+
- upstream(공공데이터포털) 이 일시 장애이면 `502 upstream_error` + `upstream_code` 를 돌려준다. 재시도는 캐시되지 않으므로 바로 다시 호출해도 된다.
|
|
188
|
+
- upstream 이 XML 에러 envelope(`OpenAPI_ServiceResponse`) 를 돌려주면 `502 upstream_error` + `upstream_code`(예: `30` = 등록되지 않은 서비스키) 로 변환한다.
|
|
189
|
+
- 응답이 JSON 이 아니면 `502 upstream_invalid_payload` 로 내려간다.
|
|
190
|
+
|
|
191
|
+
## Done when
|
|
192
|
+
|
|
193
|
+
- 사용자의 지역·공고 유형·상태 의도에 맞춰 적어도 한 번 `/v1/lh-notice/search` 를 호출했다.
|
|
194
|
+
- 결과에 공고명, 지역, 공고일/마감일, 상태, 공식 링크가 모두 포함되어 있다.
|
|
195
|
+
- 마감 여부를 KST 기준으로 판정해 표기했다.
|
|
196
|
+
- 필요하면 상세 조회로 이어가거나 사용자가 스스로 상세를 조회할 수 있도록 `panId`/`ccrCnntSysDsCd`/`splInfTpCd` 를 함께 안내했다.
|
|
197
|
+
|
|
198
|
+
## Notes
|
|
199
|
+
|
|
200
|
+
- 공식 LH 청약플러스 포털: `https://apply.lh.or.kr/lhapply/apply/wt/wrtanc/selectWrtancList.do?mi=1026`
|
|
201
|
+
- 공공데이터포털 카탈로그: `https://www.data.go.kr/data/15058530/openapi.do` (LH 임대공고문 정보)
|
|
202
|
+
- upstream `panSs` 값은 한국어로 정확히 맞춰서 보낸다. 영문/공백 변형은 받지 않는다.
|
|
203
|
+
- 대분류/세부분류 코드 매핑 참고:
|
|
204
|
+
- `06` 임대주택: `09` 영구임대, `10` 행복주택, `17` 전세임대, `08` 국민임대, `26` 매입임대 등
|
|
205
|
+
- `13` 주거복지: `17` 전세임대, 신혼희망타운 등
|
|
206
|
+
- `05` 분양주택, `01` 토지, `22` 상가
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lh-notice-search",
|
|
3
|
+
"description": "Search official LH 청약 (Korea Land & Housing Corporation lease/subscription) 공고 lists through k-skill-proxy. Use when a user asks about 청년/행복/영구/국민/매입/전세임대, 분양주택, 신혼희망타운 공고 marketed on apply.lh.or.kr. 돌쇠에서는 공식 표면을 통한 후속 액션까지 진행한다.",
|
|
4
|
+
"profiles": [
|
|
5
|
+
"proxy",
|
|
6
|
+
"vault",
|
|
7
|
+
"action:submission"
|
|
8
|
+
],
|
|
9
|
+
"frontmatter": "name: lh-notice-search\ndescription: Search official LH 청약 (Korea Land & Housing Corporation lease/subscription) 공고 lists through k-skill-proxy. Use when a user asks about 청년/행복/영구/국민/매입/전세임대, 분양주택, 신혼희망타운 공고 marketed on apply.lh.or.kr. 돌쇠에서는 공식 표면을 통한 후속 액션까지 진행한다.\nlicense: MIT\nmetadata:\n category: real-estate\n locale: ko-KR\n phase: v1"
|
|
10
|
+
}
|