@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,358 @@
|
|
|
1
|
+
# Delivery Tracking
|
|
2
|
+
|
|
3
|
+
## What this skill does
|
|
4
|
+
|
|
5
|
+
CJ대한통운과 우체국 공식 조회 표면을 사용해 송장 번호로 현재 배송 상태를 조회한다.
|
|
6
|
+
|
|
7
|
+
- **CJ대한통운**: 공식 배송조회 페이지가 노출하는 JSON endpoint 사용
|
|
8
|
+
- **우체국**: 공식 배송조회 페이지가 사용하는 HTML endpoint 사용
|
|
9
|
+
- 결과는 공통 포맷(택배사 / 송장번호 / 현재 상태 / 최근 이벤트들)으로 짧게 정리
|
|
10
|
+
|
|
11
|
+
## When to use
|
|
12
|
+
|
|
13
|
+
- "CJ대한통운 송장 조회해줘"
|
|
14
|
+
- "우체국 택배 지금 어디야"
|
|
15
|
+
- "이 송장번호 배송완료인지 확인해줘"
|
|
16
|
+
- "택배사별 조회 로직을 나중에 더 붙일 수 있게 정리해줘"
|
|
17
|
+
|
|
18
|
+
## When not to use
|
|
19
|
+
|
|
20
|
+
- 주문번호만 있고 송장번호가 없는 경우
|
|
21
|
+
- 택배 예약/반품 접수까지 바로 해야 하는 경우
|
|
22
|
+
- 비공식 통합 배송조회 서비스로 우회하고 싶은 경우
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
- 인터넷 연결
|
|
27
|
+
- `python3`
|
|
28
|
+
- `curl`
|
|
29
|
+
- 선택 사항: `jq`
|
|
30
|
+
|
|
31
|
+
## Inputs
|
|
32
|
+
|
|
33
|
+
- 택배사 식별자: `cj` 또는 `epost`
|
|
34
|
+
- 송장번호
|
|
35
|
+
- CJ대한통운: 숫자 10자리 또는 12자리
|
|
36
|
+
- 우체국: 숫자 13자리
|
|
37
|
+
|
|
38
|
+
## Carrier adapter rule
|
|
39
|
+
|
|
40
|
+
이 스킬은 택배사별 로직을 **carrier adapter** 단위로 나눈다.
|
|
41
|
+
|
|
42
|
+
새 택배사를 붙일 때는 아래 필드를 먼저 정한다.
|
|
43
|
+
|
|
44
|
+
- `carrier id`: 예) `cj`, `epost`
|
|
45
|
+
- `validator`: 송장번호 자리수/패턴
|
|
46
|
+
- `entrypoint`: 공식 조회 진입 URL
|
|
47
|
+
- `transport`: JSON API / HTML form / CLI 중 무엇을 쓰는지
|
|
48
|
+
- `parser`: 어떤 필드나 테이블에서 상태를 뽑는지
|
|
49
|
+
- `status map`: 각 택배사의 원본 상태 코드를 공통 상태로 어떻게 줄일지
|
|
50
|
+
- `retry policy`: timeout/retry 규칙
|
|
51
|
+
|
|
52
|
+
현재 어댑터는 아래 둘이다.
|
|
53
|
+
|
|
54
|
+
| carrier adapter | official entry | transport | validator | parser focus |
|
|
55
|
+
| --- | --- | --- | --- | --- |
|
|
56
|
+
| `cj` | `https://www.cjlogistics.com/ko/tool/parcel/tracking` | page GET + `tracking-detail` POST JSON | 10자리 또는 12자리 숫자 | `parcelDetailResultMap.resultList` |
|
|
57
|
+
| `epost` | `https://service.epost.go.kr/trace.RetrieveRegiPrclDeliv.postal?sid1=` | form POST HTML | 13자리 숫자 | 기본정보 `table_col` + 상세 `processTable` |
|
|
58
|
+
|
|
59
|
+
## Workflow
|
|
60
|
+
|
|
61
|
+
### 0. Normalize the input first
|
|
62
|
+
|
|
63
|
+
- 택배사 이름을 `cj` / `epost` 둘 중 하나로 정규화한다.
|
|
64
|
+
- 송장번호에서 공백과 `-` 를 제거한다.
|
|
65
|
+
- 자리수 검증이 먼저 실패하면 조회를 보내지 않는다.
|
|
66
|
+
|
|
67
|
+
### 1. CJ대한통운: official JSON flow
|
|
68
|
+
|
|
69
|
+
공식 진입 페이지에서 `_csrf` 를 읽고, 그 값을 `tracking-detail` POST에 같이 보낸다.
|
|
70
|
+
|
|
71
|
+
- 진입 페이지: `https://www.cjlogistics.com/ko/tool/parcel/tracking`
|
|
72
|
+
- 상세 endpoint: `https://www.cjlogistics.com/ko/tool/parcel/tracking-detail`
|
|
73
|
+
- 필수 필드: `_csrf`, `paramInvcNo`
|
|
74
|
+
|
|
75
|
+
기본 예시는 `curl` 로 `_csrf` 와 cookie를 유지하고, Python은 JSON 정리에만 쓴다.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
tmp_body="$(mktemp)"
|
|
79
|
+
tmp_cookie="$(mktemp)"
|
|
80
|
+
tmp_json="$(mktemp)"
|
|
81
|
+
invoice="1234567890" # 공식 페이지 placeholder 성격의 smoke-test 값
|
|
82
|
+
|
|
83
|
+
curl -sS -L -c "$tmp_cookie" \
|
|
84
|
+
"https://www.cjlogistics.com/ko/tool/parcel/tracking" \
|
|
85
|
+
-o "$tmp_body"
|
|
86
|
+
|
|
87
|
+
csrf="$(python3 - <<'PY' "$tmp_body"
|
|
88
|
+
import re
|
|
89
|
+
import sys
|
|
90
|
+
|
|
91
|
+
text = open(sys.argv[1], encoding="utf-8", errors="ignore").read()
|
|
92
|
+
print(re.search(r'name="_csrf" value="([^"]+)"', text).group(1))
|
|
93
|
+
PY
|
|
94
|
+
)"
|
|
95
|
+
|
|
96
|
+
curl -sS -L -b "$tmp_cookie" \
|
|
97
|
+
-H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
|
|
98
|
+
--data-urlencode "_csrf=$csrf" \
|
|
99
|
+
--data-urlencode "paramInvcNo=$invoice" \
|
|
100
|
+
"https://www.cjlogistics.com/ko/tool/parcel/tracking-detail" \
|
|
101
|
+
-o "$tmp_json"
|
|
102
|
+
|
|
103
|
+
python3 - <<'PY' "$tmp_json"
|
|
104
|
+
import json
|
|
105
|
+
import sys
|
|
106
|
+
|
|
107
|
+
payload = json.load(open(sys.argv[1], encoding="utf-8"))
|
|
108
|
+
events = payload["parcelDetailResultMap"]["resultList"]
|
|
109
|
+
if not events:
|
|
110
|
+
raise SystemExit("조회 결과가 없습니다.")
|
|
111
|
+
|
|
112
|
+
status_map = {
|
|
113
|
+
"11": "상품인수",
|
|
114
|
+
"21": "상품이동중",
|
|
115
|
+
"41": "상품이동중",
|
|
116
|
+
"42": "배송지도착",
|
|
117
|
+
"44": "상품이동중",
|
|
118
|
+
"82": "배송출발",
|
|
119
|
+
"91": "배달완료",
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
latest = events[-1]
|
|
123
|
+
normalized_events = [
|
|
124
|
+
{
|
|
125
|
+
"timestamp": event.get("dTime"),
|
|
126
|
+
"location": event.get("regBranNm"),
|
|
127
|
+
"status_code": event.get("crgSt"),
|
|
128
|
+
"status": status_map.get(event.get("crgSt"), event.get("scanNm") or "알수없음"),
|
|
129
|
+
}
|
|
130
|
+
for event in events
|
|
131
|
+
]
|
|
132
|
+
print(json.dumps({
|
|
133
|
+
"carrier": "cj",
|
|
134
|
+
"invoice": payload["parcelDetailResultMap"]["paramInvcNo"],
|
|
135
|
+
"status_code": latest.get("crgSt"),
|
|
136
|
+
"status": status_map.get(latest.get("crgSt"), latest.get("scanNm") or "알수없음"),
|
|
137
|
+
"timestamp": latest.get("dTime"),
|
|
138
|
+
"location": latest.get("regBranNm"),
|
|
139
|
+
"event_count": len(events),
|
|
140
|
+
"recent_events": normalized_events[-min(3, len(normalized_events)):],
|
|
141
|
+
}, ensure_ascii=False, indent=2))
|
|
142
|
+
PY
|
|
143
|
+
|
|
144
|
+
rm -f "$tmp_body" "$tmp_cookie" "$tmp_json"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### CJ 공개 출력 예시
|
|
148
|
+
|
|
149
|
+
아래 값은 2026-03-27 기준 live smoke test(`1234567890`)에서 확인한 정규화 결과다.
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"carrier": "cj",
|
|
154
|
+
"invoice": "1234567890",
|
|
155
|
+
"status_code": "91",
|
|
156
|
+
"status": "배달완료",
|
|
157
|
+
"timestamp": "2026-03-21 12:22:13",
|
|
158
|
+
"location": "경기광주오포",
|
|
159
|
+
"event_count": 3,
|
|
160
|
+
"recent_events": [
|
|
161
|
+
{
|
|
162
|
+
"timestamp": "2026-03-10 03:01:45",
|
|
163
|
+
"location": "청원HUB",
|
|
164
|
+
"status_code": "44",
|
|
165
|
+
"status": "상품이동중"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"timestamp": "2026-03-21 10:53:19",
|
|
169
|
+
"location": "경기광주오포",
|
|
170
|
+
"status_code": "82",
|
|
171
|
+
"status": "배송출발"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"timestamp": "2026-03-21 12:22:13",
|
|
175
|
+
"location": "경기광주오포",
|
|
176
|
+
"status_code": "91",
|
|
177
|
+
"status": "배달완료"
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
추가 smoke test 로는 `000000000000` 도 사용할 수 있다.
|
|
184
|
+
|
|
185
|
+
CJ 응답은 `parcelResultMap.resultList` 가 비어 있어도 `parcelDetailResultMap.resultList` 쪽에 이벤트가 들어올 수 있으므로, 상세 이벤트 배열을 우선 본다. published 예시는 공통 결과 스키마(`carrier`, `invoice`, `status`, `timestamp`, `location`, `event_count`, `recent_events`, 선택적 `status_code`)에 맞춰 비식별 필드만 남기고, 담당자 이름·연락처가 섞일 수 있는 `crgNm` 원문은 그대로 보여주지 않는다.
|
|
186
|
+
|
|
187
|
+
### 2. 우체국: official HTML flow
|
|
188
|
+
|
|
189
|
+
우체국은 공식 entry page가 다시 `trace.RetrieveDomRigiTraceList.comm` 으로 `sid1` 을 POST하는 구조다.
|
|
190
|
+
|
|
191
|
+
- 진입 페이지: `https://service.epost.go.kr/trace.RetrieveRegiPrclDeliv.postal?sid1=`
|
|
192
|
+
- 실제 조회 endpoint: `https://service.epost.go.kr/trace.RetrieveDomRigiTraceList.comm`
|
|
193
|
+
- 필수 필드: `sid1`
|
|
194
|
+
|
|
195
|
+
우체국은 로컬 Python HTTP client보다 `curl --http1.1 --tls-max 1.2` 경로가 더 안정적이므로 그 조합을 기본 예시로 쓴다.
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
tmp_html="$(mktemp)"
|
|
199
|
+
python3 - <<'PY' "$tmp_html"
|
|
200
|
+
import html
|
|
201
|
+
import json
|
|
202
|
+
import re
|
|
203
|
+
import subprocess
|
|
204
|
+
import sys
|
|
205
|
+
|
|
206
|
+
invoice = "1234567890123" # 공식 페이지 placeholder 성격의 smoke-test 값
|
|
207
|
+
output_path = sys.argv[1]
|
|
208
|
+
|
|
209
|
+
cmd = [
|
|
210
|
+
"curl",
|
|
211
|
+
"--http1.1",
|
|
212
|
+
"--tls-max",
|
|
213
|
+
"1.2",
|
|
214
|
+
"--silent",
|
|
215
|
+
"--show-error",
|
|
216
|
+
"--location",
|
|
217
|
+
"--retry",
|
|
218
|
+
"3",
|
|
219
|
+
"--retry-all-errors",
|
|
220
|
+
"--retry-delay",
|
|
221
|
+
"1",
|
|
222
|
+
"--max-time",
|
|
223
|
+
"30",
|
|
224
|
+
"-o",
|
|
225
|
+
output_path,
|
|
226
|
+
"-d",
|
|
227
|
+
f"sid1={invoice}",
|
|
228
|
+
"https://service.epost.go.kr/trace.RetrieveDomRigiTraceList.comm",
|
|
229
|
+
]
|
|
230
|
+
subprocess.run(cmd, check=True)
|
|
231
|
+
|
|
232
|
+
page = open(output_path, encoding="utf-8", errors="ignore").read()
|
|
233
|
+
|
|
234
|
+
summary = re.search(
|
|
235
|
+
r"<th scope=\"row\">(?P<tracking>[^<]+)</th>.*?"
|
|
236
|
+
r"<td>(?P<sender>.*?)</td>.*?"
|
|
237
|
+
r"<td>(?P<receiver>.*?)</td>.*?"
|
|
238
|
+
r"<td>(?P<delivered_to>.*?)</td>.*?"
|
|
239
|
+
r"<td>(?P<kind>.*?)</td>.*?"
|
|
240
|
+
r"<td>(?P<result>.*?)</td>",
|
|
241
|
+
page,
|
|
242
|
+
re.S,
|
|
243
|
+
)
|
|
244
|
+
if not summary:
|
|
245
|
+
raise SystemExit("기본정보 테이블을 찾지 못했습니다.")
|
|
246
|
+
|
|
247
|
+
def clean(raw: str) -> str:
|
|
248
|
+
text = re.sub(r"<[^>]+>", " ", raw)
|
|
249
|
+
return " ".join(html.unescape(text).split())
|
|
250
|
+
|
|
251
|
+
def clean_location(raw: str) -> str:
|
|
252
|
+
text = clean(raw)
|
|
253
|
+
return re.sub(r"\s*(TEL\s*:?\s*)?\d{2,4}[.\-]\d{3,4}[.\-]\d{4}", "", text).strip()
|
|
254
|
+
|
|
255
|
+
events = re.findall(
|
|
256
|
+
r"<tr>\s*<td>(\d{4}\.\d{2}\.\d{2})</td>\s*"
|
|
257
|
+
r"<td>(\d{2}:\d{2})</td>\s*"
|
|
258
|
+
r"<td>(.*?)</td>\s*"
|
|
259
|
+
r"<td>\s*<span class=\"evtnm\">(.*?)</span>(.*?)</td>\s*</tr>",
|
|
260
|
+
page,
|
|
261
|
+
re.S,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
normalized_events = [
|
|
265
|
+
{
|
|
266
|
+
"timestamp": f"{day} {time_}",
|
|
267
|
+
"location": clean_location(location),
|
|
268
|
+
"status": clean(status),
|
|
269
|
+
}
|
|
270
|
+
for day, time_, location, status, _detail in events
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
latest_event = normalized_events[-1] if normalized_events else None
|
|
274
|
+
|
|
275
|
+
print(json.dumps({
|
|
276
|
+
"carrier": "epost",
|
|
277
|
+
"invoice": clean(summary.group("tracking")),
|
|
278
|
+
"status": clean(summary.group("result")),
|
|
279
|
+
"timestamp": latest_event["timestamp"] if latest_event else None,
|
|
280
|
+
"location": latest_event["location"] if latest_event else None,
|
|
281
|
+
"event_count": len(normalized_events),
|
|
282
|
+
"recent_events": normalized_events[-min(3, len(normalized_events)):],
|
|
283
|
+
}, ensure_ascii=False, indent=2))
|
|
284
|
+
PY
|
|
285
|
+
rm -f "$tmp_html"
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
#### 우체국 공개 출력 예시
|
|
289
|
+
|
|
290
|
+
아래 값은 2026-03-27 기준 live smoke test(`1234567890123`)에서 확인한 정규화 결과다.
|
|
291
|
+
|
|
292
|
+
```json
|
|
293
|
+
{
|
|
294
|
+
"carrier": "epost",
|
|
295
|
+
"invoice": "1234567890123",
|
|
296
|
+
"status": "배달완료",
|
|
297
|
+
"timestamp": "2025.12.04 15:13",
|
|
298
|
+
"location": "제주우편집중국",
|
|
299
|
+
"event_count": 2,
|
|
300
|
+
"recent_events": [
|
|
301
|
+
{
|
|
302
|
+
"timestamp": "2025.12.04 15:13",
|
|
303
|
+
"location": "제주우편집중국",
|
|
304
|
+
"status": "배달준비"
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
"timestamp": "2025.12.04 15:13",
|
|
308
|
+
"location": "제주우편집중국",
|
|
309
|
+
"status": "배달완료"
|
|
310
|
+
}
|
|
311
|
+
]
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
우체국 기본정보 테이블은 `등기번호`, `보내는 분/접수일자`, `받는 분`, `수령인/배달일자`, `취급구분`, `배달결과` 순서를 사용하고, 상세 이벤트는 `processTable` 아래 `날짜 / 시간 / 발생국 / 처리현황` 행을 읽으면 된다. published 예시는 CJ와 같은 공통 결과 스키마(`carrier`, `invoice`, `status`, `timestamp`, `location`, `event_count`, `recent_events`)에 맞춰 배송 상태에 필요한 값만 남기고, 이벤트 location에 섞일 수 있는 `TEL` 번호 조각도 제거한 뒤 수령인/상세 메모 원문은 그대로 노출하지 않는다.
|
|
316
|
+
|
|
317
|
+
### 3. Normalize for humans
|
|
318
|
+
|
|
319
|
+
응답 원문을 그대로 붙이지 말고 아래 공통 결과 스키마로 요약한다.
|
|
320
|
+
|
|
321
|
+
#### 공통 결과 스키마
|
|
322
|
+
|
|
323
|
+
- `carrier`: 택배사 식별자 (`cj` 또는 `epost`)
|
|
324
|
+
- `invoice`: 정규화된 송장번호
|
|
325
|
+
- `status`: 현재 배송 상태
|
|
326
|
+
- `timestamp`: 마지막 이벤트 시각
|
|
327
|
+
- `location`: 마지막 이벤트 위치
|
|
328
|
+
- `event_count`: 전체 이벤트 수
|
|
329
|
+
- `recent_events`: 최근 최대 3개 이벤트 목록
|
|
330
|
+
- `status_code`: 필요할 때만 남기는 원본 상태 코드 (현재는 CJ 예시에서만 사용)
|
|
331
|
+
|
|
332
|
+
### 4. Retry and fallback policy
|
|
333
|
+
|
|
334
|
+
- 자리수 오류면 바로 멈추고 올바른 형식을 다시 받는다.
|
|
335
|
+
- CJ는 `_csrf` 재취득 후 한 번 더 시도한다.
|
|
336
|
+
- 우체국은 `curl --retry 3 --retry-all-errors --retry-delay 1` 을 유지한다.
|
|
337
|
+
- 다른 택배사로 우회하지 않는다.
|
|
338
|
+
|
|
339
|
+
## Done when
|
|
340
|
+
|
|
341
|
+
- 택배사와 송장번호가 올바르게 식별되어 있다
|
|
342
|
+
- 현재 상태와 최근 이벤트가 정리되어 있다
|
|
343
|
+
- 어느 official surface를 썼는지 설명할 수 있다
|
|
344
|
+
- 다른 택배사 확장 시 어떤 carrier adapter 필드를 추가해야 하는지 남아 있다
|
|
345
|
+
|
|
346
|
+
## Failure modes
|
|
347
|
+
|
|
348
|
+
- CJ: `_csrf` 추출 실패 또는 `tracking-detail` 응답 스키마 변경
|
|
349
|
+
- CJ: 송장번호 길이가 10자리 또는 12자리가 아님
|
|
350
|
+
- 우체국: `sid1` 이 13자리가 아님
|
|
351
|
+
- 우체국: HTML 마크업 변경으로 테이블 추출 규칙이 깨짐
|
|
352
|
+
- 우체국: `curl` 없이 다른 client로 붙다가 timeout/reset 발생
|
|
353
|
+
|
|
354
|
+
## Notes
|
|
355
|
+
|
|
356
|
+
- 조회형 스킬이다.
|
|
357
|
+
- 기본 표면은 공식 carrier endpoint만 사용한다.
|
|
358
|
+
- 다른 택배사 추가는 새 carrier adapter 1개를 같은 포맷으로 붙이는 방식으로 확장한다.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "delivery-tracking",
|
|
3
|
+
"description": "Track CJ대한통운 and 우체국 parcels by invoice number with official carrier endpoints, and structure the workflow around a carrier adapter that can grow to more couriers later.",
|
|
4
|
+
"profiles": [
|
|
5
|
+
"lookup"
|
|
6
|
+
],
|
|
7
|
+
"frontmatter": "name: delivery-tracking\ndescription: Track CJ대한통운 and 우체국 parcels by invoice number with official carrier endpoints, and structure the workflow around a carrier adapter that can grow to more couriers later.\nlicense: MIT\nmetadata:\n category: logistics\n locale: ko-KR\n phase: v1"
|
|
8
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# 기부처 조회 / Donation Place Search
|
|
2
|
+
|
|
3
|
+
## What this skill does
|
|
4
|
+
|
|
5
|
+
사용자가 “어디에 기부하면 좋을지”, “서울 아동 기부처”, “동물보호 기부처 추천”처럼 묻는 경우 **장소와 카테고리 기준으로 기부처 후보를 추천**한다.
|
|
6
|
+
|
|
7
|
+
- 기부를 대신 실행하지 않는다.
|
|
8
|
+
- 결제, 개인정보 입력, 자동 후원 신청은 하지 않는다.
|
|
9
|
+
- 추천은 의사결정 보조이며, 최종 기부 전 공식 페이지와 1365 기부포털에서 최신 등록·모금기간·기부금영수증 가능 여부를 확인한다.
|
|
10
|
+
- 위치는 사용자가 제공한 행정구역/동네/랜드마크 텍스트만 사용한다. 자동 위치 추적을 하지 않는다.
|
|
11
|
+
|
|
12
|
+
## When to use
|
|
13
|
+
|
|
14
|
+
- “기부처 조회해줘”
|
|
15
|
+
- “서울 마포구에서 동물보호 기부할 만한 곳 추천해줘”
|
|
16
|
+
- “부산 노인 복지 기부처 알려줘”
|
|
17
|
+
- “아동/재난 분야 기부처 비교해줘”
|
|
18
|
+
- “어디에 기부하는 곳이 좋을지 장소와 카테고리별로 추천해줘”
|
|
19
|
+
|
|
20
|
+
## Inputs
|
|
21
|
+
|
|
22
|
+
- `location`: 선택. 예: `서울 마포구`, `부산 해운대구`, `제주`, `온라인`
|
|
23
|
+
- `category`: 선택. 예: `아동`, `동물보호`, `환경`, `재난 구호`, `장애`, `노인`, `생계`, `의료`, `해외구호`
|
|
24
|
+
- `limit`: 선택. 기본 5개
|
|
25
|
+
|
|
26
|
+
위치나 카테고리가 없으면 보수적으로 `전국`·`일반/종합` 후보와 1365 공식 확인 보조 링크를 제공한다. 비대화형 자동화에서는 임의로 좁히지 말고 “입력 없음”을 명시한다.
|
|
27
|
+
|
|
28
|
+
## Public access path discovered
|
|
29
|
+
|
|
30
|
+
### Primary official verification surface
|
|
31
|
+
|
|
32
|
+
- Legacy `https://www.nanumkorea.go.kr/` currently returns a notice that 1365 기부포털 has moved/integrated into 1365 자원봉사.
|
|
33
|
+
- The notice links to `https://www.1365.go.kr/dntn/main.do`.
|
|
34
|
+
- The skill therefore uses `https://www.1365.go.kr/dntn/main.do` as the official public verification entry point.
|
|
35
|
+
|
|
36
|
+
### Search-link strategy
|
|
37
|
+
|
|
38
|
+
1365 pages can be slow or unavailable to headless HTTP clients, so the package does not depend on brittle screen scraping. It builds a best-effort official-entry/search-assist link with the user’s location/category keywords, then ranks a curated fallback list locally. The package does not assert that 1365 has already verified each returned candidate:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
const { recommendDonationPlaces } = require("donation-place-search");
|
|
42
|
+
|
|
43
|
+
const result = recommendDonationPlaces({
|
|
44
|
+
location: "서울 마포구",
|
|
45
|
+
category: "동물",
|
|
46
|
+
limit: 3
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
console.log(result.items);
|
|
50
|
+
console.log(result.officialSearchUrl);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The returned `officialSearchUrl` is a best-effort verification assist: open it as an official 1365 entry point, then confirm current registration and campaign status before giving the final answer.
|
|
54
|
+
|
|
55
|
+
## Workflow
|
|
56
|
+
|
|
57
|
+
1. Extract `location`, `category`, and optional `limit` from the user request.
|
|
58
|
+
2. Run the helper:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
node - <<'NODE'
|
|
62
|
+
const {
|
|
63
|
+
recommendDonationPlaces,
|
|
64
|
+
formatDonationRecommendationReport
|
|
65
|
+
} = require("donation-place-search");
|
|
66
|
+
|
|
67
|
+
const result = recommendDonationPlaces({
|
|
68
|
+
location: "서울 마포구",
|
|
69
|
+
category: "동물",
|
|
70
|
+
limit: 3
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
console.log(formatDonationRecommendationReport(result));
|
|
74
|
+
NODE
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
3. Open or cite the returned best-effort 1365 verification-assist URL for latest verification when fresh browsing is available.
|
|
78
|
+
4. Summarize 3–5 candidates, including:
|
|
79
|
+
- 기부처명
|
|
80
|
+
- 분야/카테고리
|
|
81
|
+
- 지역 일치 여부 또는 전국 단위 여부
|
|
82
|
+
- 왜 맞는지 한 줄
|
|
83
|
+
- 공식 홈페이지
|
|
84
|
+
- 1365 확인 보조 링크
|
|
85
|
+
5. Add a caution that campaign status, donation receipt eligibility, and designated-use options must be checked on official pages before donating.
|
|
86
|
+
|
|
87
|
+
## Output fields
|
|
88
|
+
|
|
89
|
+
The npm helper returns:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"location": { "raw": "서울 마포구", "province": "서울", "district": "마포구" },
|
|
94
|
+
"category": "animals",
|
|
95
|
+
"items": [
|
|
96
|
+
{
|
|
97
|
+
"name": "동물권행동 카라",
|
|
98
|
+
"categories": ["animals"],
|
|
99
|
+
"coverage": "local",
|
|
100
|
+
"homepageUrl": "https://www.ekara.org/",
|
|
101
|
+
"officialSearchUrl": "https://www.1365.go.kr/dntn/main.do?...",
|
|
102
|
+
"match": { "category": true, "local": true, "nationwide": false }
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"officialSearchUrl": "https://www.1365.go.kr/dntn/main.do?...",
|
|
106
|
+
"meta": { "source": "curated-fallback-plus-1365-search-assist" }
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Done when
|
|
111
|
+
|
|
112
|
+
- 장소/카테고리 조건을 반영해 후보를 3–5개 이내로 정리했다.
|
|
113
|
+
- 각 후보마다 공식 홈페이지 또는 1365 확인 보조 링크를 제공했다.
|
|
114
|
+
- 최종 기부 전 등록 상태, 모금 기간, 기부금영수증 가능 여부를 확인하라고 안내했다.
|
|
115
|
+
- 자동 결제/후원 신청을 시도하지 않았다.
|
|
116
|
+
|
|
117
|
+
## Failure modes
|
|
118
|
+
|
|
119
|
+
- 1365 사이트가 느리거나 headless HTTP에서 timeout/empty page를 반환할 수 있다. 이 경우 확인 보조 URL과 후보 홈페이지를 제공하고 “최신 상태는 직접 확인 필요”라고 명시한다.
|
|
120
|
+
- 위치 문자열이 행정구역으로 파싱되지 않으면 전국 후보 위주로 제안한다.
|
|
121
|
+
- 지역·카테고리 모두 정확히 맞는 후보가 없으면 전국 단위 후보를 fallback으로 보여준다.
|
|
122
|
+
- 특정 단체의 모금 캠페인, 지정기부 가능 여부, 기부금영수증 처리는 수시로 바뀌므로 package 내 curated 설명만으로 확정하지 않는다.
|
|
123
|
+
- 로그인, 결제, CAPTCHA, 후원 신청서 제출은 자동화하지 않는다.
|
|
124
|
+
|
|
125
|
+
## Notes
|
|
126
|
+
|
|
127
|
+
- 이 스킬은 read-only 추천/조회 스킬이다.
|
|
128
|
+
- 기부는 금전 의사결정이므로 최신 공식 근거를 우선한다.
|
|
129
|
+
- 공개 표면만 사용하므로 `k-skill-proxy`와 API key가 필요 없다.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "donation-place-search",
|
|
3
|
+
"description": "Use when the user asks where to donate, 기부처 조회, or donation place recommendations by Korean location and category. Recommend recipients with best-effort 1365 verification-assist links and never execute donations. 돌쇠에서는 공식 표면을 통한 후속 액션까지 진행한다.",
|
|
4
|
+
"profiles": [
|
|
5
|
+
"proxy",
|
|
6
|
+
"action:submission"
|
|
7
|
+
],
|
|
8
|
+
"frontmatter": "name: donation-place-search\ndescription: Use when the user asks where to donate, 기부처 조회, or donation place recommendations by Korean location and category. Recommend recipients with best-effort 1365 verification-assist links and never execute donations. 돌쇠에서는 공식 표면을 통한 후속 액션까지 진행한다.\nlicense: MIT\nmetadata:\n category: utility\n locale: ko-KR\n phase: v1"
|
|
9
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Emergency Room Beds
|
|
2
|
+
|
|
3
|
+
## What this skill does
|
|
4
|
+
|
|
5
|
+
사용자가 알려준 현재 위치를 기준으로 **근처 응급실**과 공개 E-Gen 응급실 상태 플래그를 찾는다.
|
|
6
|
+
|
|
7
|
+
- 위치는 자동 추정하지 않는다.
|
|
8
|
+
- 위치가 없으면 먼저 현재 위치를 묻는다.
|
|
9
|
+
- 위치 문자열은 Kakao Map anchor 검색으로 좌표를 잡는다.
|
|
10
|
+
- 응급실 목록은 E-Gen 공개 응급실 찾기 표면을 사용한다.
|
|
11
|
+
- 응급실 운영 여부, 입원실/병상 운영 플래그, 권역외상센터/소아전문 여부, 데이터 갱신시각을 보여준다.
|
|
12
|
+
- **정확한 실시간 잔여 병상 수나 병상 가동률을 확정해서 말하지 않는다.** 공개 E-Gen nearby 목록은 병상 수치가 아니라 운영 플래그를 제공한다.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
- "근처 응급실 찾아줘"
|
|
17
|
+
- "응급실 병상 상태 확인해줘"
|
|
18
|
+
- "광화문 주변 응급실 어디가 가까워?"
|
|
19
|
+
- "현재 위치 근처 응급실 운영 여부 알려줘"
|
|
20
|
+
|
|
21
|
+
## Mandatory first question
|
|
22
|
+
|
|
23
|
+
위치 정보가 없으면 먼저 물어본다.
|
|
24
|
+
|
|
25
|
+
`현재 위치를 알려주세요. 동네/역명/랜드마크/위도·경도 중 편한 형식으로 보내주시면 근처 응급실 상태를 찾아볼게요.`
|
|
26
|
+
|
|
27
|
+
## Official/public surfaces
|
|
28
|
+
|
|
29
|
+
- NEMC 모니터링: `https://dw.nemc.or.kr/nemcMonitoring/mainmgr/Main.do`
|
|
30
|
+
- E-Gen 응급실 찾기: `https://www.e-gen.or.kr/egen/search_emergency_room.do`
|
|
31
|
+
- E-Gen nearby list endpoint: `https://www.e-gen.or.kr/egen/retrieve_emergency_room_list.do`
|
|
32
|
+
- Kakao Map 모바일 검색: `https://m.map.kakao.com/actions/searchView?q=<query>`
|
|
33
|
+
- Kakao Map 장소 패널 JSON: `https://place-api.map.kakao.com/places/panel3/<confirmId>`
|
|
34
|
+
|
|
35
|
+
## Workflow
|
|
36
|
+
|
|
37
|
+
1. 사용자의 현재 위치를 확보한다.
|
|
38
|
+
2. `emergency-room-beds` 패키지의 `searchNearbyEmergencyRoomsByLocationQuery()`를 사용한다.
|
|
39
|
+
3. 보통 3~5개 이내로 거리순 결과를 정리한다.
|
|
40
|
+
4. 반드시 "공개 E-Gen nearby 목록 기준이며 정확한 잔여 병상 수/가동률은 제공되지 않는다"고 밝힌다.
|
|
41
|
+
5. 긴급 상황이면 119 또는 병원 전화 확인을 권한다.
|
|
42
|
+
|
|
43
|
+
## Responding
|
|
44
|
+
|
|
45
|
+
결과는 짧고 실용적으로 정리한다.
|
|
46
|
+
|
|
47
|
+
- 병원명 / 거리
|
|
48
|
+
- 응급의료기관 등급 / 병원 유형
|
|
49
|
+
- 응급실 운영 여부
|
|
50
|
+
- 입원실/병상 운영 플래그
|
|
51
|
+
- 권역외상센터/소아전문 여부
|
|
52
|
+
- 주소 / 대표전화
|
|
53
|
+
- 갱신시각
|
|
54
|
+
- 지도 링크
|
|
55
|
+
|
|
56
|
+
## Node.js example
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
const { searchNearbyEmergencyRoomsByLocationQuery } = require("emergency-room-beds");
|
|
60
|
+
|
|
61
|
+
async function main() {
|
|
62
|
+
const result = await searchNearbyEmergencyRoomsByLocationQuery("광화문", {
|
|
63
|
+
limit: 3,
|
|
64
|
+
radius: 5
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log(result.anchor);
|
|
68
|
+
console.log(result.items);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
main().catch((error) => {
|
|
72
|
+
console.error(error);
|
|
73
|
+
process.exitCode = 1;
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Done when
|
|
78
|
+
|
|
79
|
+
- 위치 기준 anchor를 확인했다.
|
|
80
|
+
- 가까운 응급실을 찾았거나, 못 찾은 이유와 다음 검색 범위를 제시했다.
|
|
81
|
+
- 공개 데이터의 한계(정확한 잔여 병상 수/가동률 미제공)를 명확히 밝혔다.
|
|
82
|
+
- 긴급 상황에서는 119/전화 확인 안내를 포함했다.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "emergency-room-beds",
|
|
3
|
+
"description": "Use when the user asks for nearby Korean emergency rooms, 응급실, ER, or emergency bed/병상 status near a location. Ask for the user's current location first unless a location was already provided.",
|
|
4
|
+
"profiles": [
|
|
5
|
+
"lookup"
|
|
6
|
+
],
|
|
7
|
+
"frontmatter": "name: emergency-room-beds\ndescription: Use when the user asks for nearby Korean emergency rooms, 응급실, ER, or emergency bed/병상 status near a location. Ask for the user's current location first unless a location was already provided.\nlicense: MIT\nmetadata:\n category: health\n locale: ko-KR\n phase: v1"
|
|
8
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# EV Charger Nearby
|
|
2
|
+
|
|
3
|
+
## What this skill does
|
|
4
|
+
|
|
5
|
+
환경부 전기차 충전소 API의 충전소 정보와 충전기 상태를 조회한다. 조회 전용이며 예약, 결제, 회원 인증, 충전 시작/중지는 자동화하지 않는다.
|
|
6
|
+
|
|
7
|
+
기본 호출은 hosted `k-skill-proxy`를 사용하므로 사용자는 API 키가 필요 없다. `--direct`를 명시한 경우에만 사용자의 `KSKILL_EV_CHARGER_API_KEY`, 이후 `DATA_GO_KR_API_KEY`를 찾는다.
|
|
8
|
+
|
|
9
|
+
## Official access path
|
|
10
|
+
|
|
11
|
+
1. 실시간 충전소 정보: 공공데이터포털 데이터셋 `15076352`, `getChargerInfo`
|
|
12
|
+
2. 실시간 충전기 상태: 같은 데이터셋의 `getChargerStatus`
|
|
13
|
+
3. 정적/수동 fallback: 전국전기차충전소표준데이터 데이터셋 `15013115`의 포털 제공 파일
|
|
14
|
+
|
|
15
|
+
`15013115`는 실시간 상태 API가 아니다. 포털 다운로드 화면에서 사용자가 직접 받은 표준 CSV를 정적 참고자료로만 사용하며, 문서화되지 않은 CSV URL을 추측하지 않는다.
|
|
16
|
+
|
|
17
|
+
## Inputs and commands
|
|
18
|
+
|
|
19
|
+
설치된 skill 디렉터리에서 실행한다.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
python3 scripts/ev_charger.py info --location '서울 강남구' --num-of-rows 10
|
|
23
|
+
python3 scripts/ev_charger.py status --stat-id ME000001 --num-of-rows 10
|
|
24
|
+
python3 scripts/ev_charger.py status --zcode 11 --limit-yn Y --period 10 --json
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
공통 필터는 `zcode`, `zscode`, `statId`, `chgerId`다. hosted proxy의 `info`는 고유하게 식별되는 `location`을 행정구역 코드로 변환하며, 모호하거나 찾을 수 없는 위치와 충돌하는 명시적 코드는 거부한다. `status`는 `limitYn`과 `period`를 추가로 허용한다. 페이지 기본값은 `pageNo=1`, `numOfRows=10`이며 `numOfRows` 범위는 10~9999다.
|
|
28
|
+
|
|
29
|
+
직접 호출:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python3 scripts/ev_charger.py info --zcode 11 --zscode 11680 --direct
|
|
33
|
+
python3 scripts/ev_charger.py status --stat-id ME000001 --direct --dry-run
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
직접 호출은 위치 텍스트를 행정구역 코드로 변환하지 않으므로 `--location` 대신 `--zcode`/`--zscode`를 사용한다. `--dry-run`은 URL을 보여주되 키를 `REDACTED`로 가린다.
|
|
37
|
+
|
|
38
|
+
## Credential rules
|
|
39
|
+
|
|
40
|
+
- hosted proxy: 사용자 키 불필요
|
|
41
|
+
- direct 환경변수 우선순위: `KSKILL_EV_CHARGER_API_KEY` -> `DATA_GO_KR_API_KEY`
|
|
42
|
+
- dotenv fallback: `~/.config/k-skill/secrets.env`에서 같은 순서
|
|
43
|
+
- 키를 로그, 답변, dry-run URL, 저장소 파일에 노출하지 않는다
|
|
44
|
+
|
|
45
|
+
공공데이터포털 인증키를 이미 갖고 있어도 데이터셋 `15076352` 상세 페이지에서 **별도 활용신청**이 필요하다. 이 API는 자동승인 대상이지만 승인/활성화가 완료된 뒤 호출해야 한다.
|
|
46
|
+
|
|
47
|
+
## Workflow and fallback order
|
|
48
|
+
|
|
49
|
+
1. 위치/지역 요청은 `info`로 충전소 주소, 운영기관, 충전기 유형과 식별자를 찾는다.
|
|
50
|
+
2. 찾은 `statId`/`chgerId`로 `status`를 호출해 현재 상태와 갱신시각을 확인한다.
|
|
51
|
+
3. live info가 실패하면 동일 조건을 좁혀 한 번 재시도한다.
|
|
52
|
+
4. live info는 성공했지만 status가 실패하면 정보 결과를 제공하면서 상태 확인 실패를 분리해 알린다.
|
|
53
|
+
5. live API 전체가 불가능할 때만 데이터셋 `15013115`의 사용자가 직접 내려받은 표준 CSV를 정적/수동 fallback으로 안내한다.
|
|
54
|
+
|
|
55
|
+
## Output
|
|
56
|
+
|
|
57
|
+
기본은 한국어 요약, `--json`은 프록시/상류 JSON을 출력한다. 가능한 경우 다음 필드를 포함한다.
|
|
58
|
+
|
|
59
|
+
- 충전소명, 주소, 위치 설명
|
|
60
|
+
- 운영기관
|
|
61
|
+
- `statId`, `chgerId`
|
|
62
|
+
- 충전기 유형과 현재 상태
|
|
63
|
+
- 상태 갱신시각
|
|
64
|
+
|
|
65
|
+
상태 코드는 원문 값을 보존한다. 상태가 없거나 오래된 경우 추정하지 않는다.
|
|
66
|
+
|
|
67
|
+
## Failure modes
|
|
68
|
+
|
|
69
|
+
- `upstream_not_configured`: hosted/self-host 프록시에 `DATA_GO_KR_API_KEY`가 없음
|
|
70
|
+
- key/auth rejection: 데이터셋 `15076352` 활용신청 승인 여부 확인
|
|
71
|
+
- proxy down: 프록시 장애 메시지를 보여주고 잠시 후 재시도
|
|
72
|
+
- empty result: 조건을 좁히거나 `zcode`/`zscode`/`statId`를 확인
|
|
73
|
+
- invalid/non-JSON/XML response: upstream 응답 오류로 분리하고 결과로 캐시하지 않음
|
|
74
|
+
- static CSV fallback: 실시간 상태로 표현하지 않고 파일 기준일을 함께 명시
|
|
75
|
+
|
|
76
|
+
## Done when
|
|
77
|
+
|
|
78
|
+
- 충전소 정보와 가능한 현재 상태를 각각 확인했다.
|
|
79
|
+
- 정보 조회와 상태 조회의 시점/실패를 구분했다.
|
|
80
|
+
- 키, 예약, 결제, 충전 제어를 노출하거나 자동화하지 않았다.
|