dsh-plugin-t-expert 0.4.38 → 0.4.48
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/CHANGELOG.md +260 -0
- package/README.md +2 -2
- package/THIRD-PARTY-NOTICES +3 -3
- package/data/experts/academic/family-education-ma/.imported-from-workbuddy +1 -1
- package/data/experts/academic/ket-prep-team/.imported-from-workbuddy +1 -1
- package/data/experts/academic/liuxue-yanxue-expert/.imported-from-workbuddy +1 -1
- package/data/experts/academic/study-fortune-compass/.imported-from-workbuddy +1 -1
- package/data/experts/company/campus-event-navigator/.imported-from-workbuddy +1 -1
- package/data/experts/company/fortune-master/.imported-from-workbuddy +1 -1
- package/data/experts/company/gaokao-advisor/.imported-from-workbuddy +1 -1
- package/data/experts/company/multi-cloud-expert/.imported-from-workbuddy +1 -1
- package/data/experts/company/multi-cloud-management-expert/.imported-from-workbuddy +1 -1
- package/data/experts/company/opc-team/.imported-from-workbuddy +1 -1
- package/data/experts/company/paper-topic-selection/.imported-from-workbuddy +1 -1
- package/data/experts/company/tanyuan-cultural-heritage-expert/.imported-from-workbuddy +1 -1
- package/data/experts/design/adort-design-expert/.imported-from-workbuddy +1 -1
- package/data/experts/design/ai-image-prompt-engineer/.imported-from-workbuddy +1 -1
- package/data/experts/design/ask-liuxiaopai/.imported-from-workbuddy +1 -1
- package/data/experts/design/delightful-experience-designer/.imported-from-workbuddy +1 -1
- package/data/experts/design/design-engine/.imported-from-workbuddy +1 -1
- package/data/experts/design/design-md-architect/.imported-from-workbuddy +1 -1
- package/data/experts/design/design-prototype-expert/.imported-from-workbuddy +1 -1
- package/data/experts/design/design-to-code/.imported-from-workbuddy +1 -1
- package/data/experts/design/diversity-visual-expert/.imported-from-workbuddy +1 -1
- package/data/experts/design/feedback-synthesis-analyst/.imported-from-workbuddy +1 -1
- package/data/experts/design/mermaid-diagram-expert/.imported-from-workbuddy +1 -1
- package/data/experts/design/migraq-team/.imported-from-workbuddy +1 -1
- package/data/experts/design/ngo-challenge-advisor/.imported-from-workbuddy +1 -1
- package/data/experts/design/product-management/.imported-from-workbuddy +1 -1
- package/data/experts/design/product-strategy-team/.imported-from-workbuddy +1 -1
- package/data/experts/design/tripstar-agent/.imported-from-workbuddy +1 -1
- package/data/experts/design/user-experience-architect/.imported-from-workbuddy +1 -1
- package/data/experts/design/user-experience-researcher/.imported-from-workbuddy +1 -1
- package/data/experts/design/workflow-assistant/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/academic-journal-selector/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/ai-data-copilot/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/aicoding-architecture-expert-team/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/aihot/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/api-dev/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/arxiv-watcher/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/cat-network-quality-analyst/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/code/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/code-review-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/data/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/data-analytics-reporter/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/database-operations/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/deep-research/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/dev-pipeline-orchestrator/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/dockerfile-gen/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/edgeone-makers-experts/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/empirical-research-team/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/engineering-assurance-team/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/engineering-workflow-skills/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/eno/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/finance-data/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/frontend/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/git-workflow-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/gpt-researcher-team/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/gstack/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/hsk-devops-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/huashu-data-pro/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/jinshuju-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/jinshuju-form-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/jinshuju-table-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/kdocs-data-table/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/llm-wiki/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/mcp-build-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/mibao-media-archivist/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/mobile-application-developer/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/modern-webapp/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/mvp-dev-expert-team/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/ncre-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/nuwa/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/omics-cdgpt-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/omics-hpc-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/omics-scbert-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/omics-scprotein-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/personal-knowledge-architect/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/prompt-engineering-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/python-fullstack-engineer/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/rum-fullstack-team/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/software-company/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/superpowers-zh/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/tencentcloud-api/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/vocab-craft-expert/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/workspace-builder/.imported-from-workbuddy +1 -1
- package/data/experts/engineering/yunzhi-qa-assistant/.imported-from-workbuddy +1 -1
- package/data/experts/finance/a-share-analysis/.imported-from-workbuddy +1 -1
- package/data/experts/finance/anti-scam-agent/.imported-from-workbuddy +1 -1
- package/data/experts/finance/believe-in-light/.imported-from-workbuddy +1 -1
- package/data/experts/finance/citongshuopro/.imported-from-workbuddy +1 -1
- package/data/experts/finance/corp-credit-due-diligence/.imported-from-workbuddy +1 -1
- package/data/experts/finance/dd-due-diligence-team/.imported-from-workbuddy +1 -1
- package/data/experts/finance/earnings-reviewer/.imported-from-workbuddy +1 -1
- package/data/experts/finance/egypt-strategic-advisory/.imported-from-workbuddy +1 -1
- package/data/experts/finance/equity-research/.imported-from-workbuddy +1 -1
- package/data/experts/finance/fin-research-expert/.imported-from-workbuddy +1 -1
- package/data/experts/finance/finance/.imported-from-workbuddy +1 -1
- package/data/experts/finance/financial-analysis/.imported-from-workbuddy +1 -1
- package/data/experts/finance/financial-tracker/.imported-from-workbuddy +1 -1
- package/data/experts/finance/fund-research-analyst/.imported-from-workbuddy +1 -1
- package/data/experts/finance/gl-reconciler/.imported-from-workbuddy +1 -1
- package/data/experts/finance/industry-sre-team/.imported-from-workbuddy +1 -1
- package/data/experts/finance/investment-banking/.imported-from-workbuddy +1 -1
- package/data/experts/finance/investment-masters-team/.imported-from-workbuddy +1 -1
- package/data/experts/finance/kyc-screener/.imported-from-workbuddy +1 -1
- package/data/experts/finance/mai-deal-advisor/.imported-from-workbuddy +1 -1
- package/data/experts/finance/market-researcher/.imported-from-workbuddy +1 -1
- package/data/experts/finance/meeting-prep-agent/.imported-from-workbuddy +1 -1
- package/data/experts/finance/mentougou-business-guide/.imported-from-workbuddy +1 -1
- package/data/experts/finance/model-builder/.imported-from-workbuddy +1 -1
- package/data/experts/finance/month-end-closer/.imported-from-workbuddy +1 -1
- package/data/experts/finance/new-share-expert/.imported-from-workbuddy +1 -1
- package/data/experts/finance/pitch-agent/.imported-from-workbuddy +1 -1
- package/data/experts/finance/private-equity/.imported-from-workbuddy +1 -1
- package/data/experts/finance/roadshow-research-team/.imported-from-workbuddy +1 -1
- package/data/experts/finance/sg-finance-tax/.imported-from-workbuddy +1 -1
- package/data/experts/finance/smart-stock-analyst/.imported-from-workbuddy +1 -1
- package/data/experts/finance/smb-finance/.imported-from-workbuddy +1 -1
- package/data/experts/finance/south-africa-strategy-advisor/.imported-from-workbuddy +1 -1
- package/data/experts/finance/statement-auditor/.imported-from-workbuddy +1 -1
- package/data/experts/finance/strategy-backtest-expert/.imported-from-workbuddy +1 -1
- package/data/experts/finance/tdx-stock-diagnostician/.imported-from-workbuddy +1 -1
- package/data/experts/finance/tdx-stock-hunter/.imported-from-workbuddy +1 -1
- package/data/experts/finance/tdx-value-assessor/.imported-from-workbuddy +1 -1
- package/data/experts/finance/terminal-veteran/.imported-from-workbuddy +1 -1
- package/data/experts/finance/trading-agent/.imported-from-workbuddy +1 -1
- package/data/experts/finance/uae-public-affairs/.imported-from-workbuddy +1 -1
- package/data/experts/finance/uae-strategic-advisor/.imported-from-workbuddy +1 -1
- package/data/experts/finance/valuation-reviewer/.imported-from-workbuddy +1 -1
- package/data/experts/finance/vietnam-finance-tax-expert/.codebuddy-plugin/plugin.json +60 -0
- package/data/experts/finance/vietnam-finance-tax-expert/.downloaded_at +1 -0
- package/data/experts/finance/{stock-partner-team → vietnam-finance-tax-expert}/.imported-from-workbuddy +2 -2
- package/data/experts/finance/vietnam-finance-tax-expert/README.md +84 -0
- package/data/experts/finance/vietnam-finance-tax-expert/persona.md +323 -0
- package/data/experts/finance/wealth-management/.imported-from-workbuddy +1 -1
- package/data/experts/finance/yahoo-finance-cli/.imported-from-workbuddy +1 -1
- package/data/experts/game-development/game-development-studio/.imported-from-workbuddy +1 -1
- package/data/experts/game-development/godot-game-script-engineer/.imported-from-workbuddy +1 -1
- package/data/experts/gis/egypt-marketing/.imported-from-workbuddy +1 -1
- package/data/experts/gis/exam-preparation-planner/.imported-from-workbuddy +1 -1
- package/data/experts/gis/lazy-travel-planner/.imported-from-workbuddy +1 -1
- package/data/experts/healthcare/patient-education-content-review-word-assistant/.imported-from-workbuddy +1 -1
- package/data/experts/healthcare/tianyu-marketing-guardian/.imported-from-workbuddy +1 -1
- package/data/experts/hr/customer-support-expert/.imported-from-workbuddy +1 -1
- package/data/experts/hr/family-education-coach/.imported-from-workbuddy +1 -1
- package/data/experts/hr/fbsir-beike-yi/.imported-from-workbuddy +1 -1
- package/data/experts/hr/hr-operations-team/.imported-from-workbuddy +1 -1
- package/data/experts/hr/ihr-ai-interviewer/.imported-from-workbuddy +1 -1
- package/data/experts/hr/ihr-conference/.imported-from-workbuddy +1 -1
- package/data/experts/hr/interview-simulator/.imported-from-workbuddy +1 -1
- package/data/experts/hr/qingflow-hr-expert/.imported-from-workbuddy +1 -1
- package/data/experts/hr/south-africa-hr-admin/.imported-from-workbuddy +1 -1
- package/data/experts/hr/xiaot/.imported-from-workbuddy +1 -1
- package/data/experts/legal/brazil-company-query/.imported-from-workbuddy +1 -1
- package/data/experts/legal/brazil-legal/.imported-from-workbuddy +1 -1
- package/data/experts/legal/brazil-rfb-expert/.imported-from-workbuddy +1 -1
- package/data/experts/legal/charity-doc-finance-expert/.imported-from-workbuddy +1 -1
- package/data/experts/legal/indonesia-bd-expert/.imported-from-workbuddy +1 -1
- package/data/experts/legal/indonesia-digital-law-expert/.imported-from-workbuddy +1 -1
- package/data/experts/legal/indonesia-pa-expert/.imported-from-workbuddy +1 -1
- package/data/experts/legal/inspection-expert/.imported-from-workbuddy +1 -1
- package/data/experts/legal/malaysia-finance-tax/.codebuddy-plugin/plugin.json +64 -0
- package/data/experts/legal/malaysia-finance-tax/.downloaded_at +1 -0
- package/data/experts/legal/malaysia-finance-tax/.imported-from-workbuddy +7 -0
- package/data/experts/legal/malaysia-finance-tax/Corpus_Index.md +239 -0
- package/data/experts/legal/malaysia-finance-tax/README.md +56 -0
- package/data/experts/legal/malaysia-finance-tax/persona.md +153 -0
- package/data/experts/legal/malaysia-finance-tax/requirements.txt +2 -0
- package/data/experts/legal/malaysia-hr-admin/.codebuddy-plugin/plugin.json +64 -0
- package/data/experts/legal/malaysia-hr-admin/.downloaded_at +1 -0
- package/data/experts/legal/malaysia-hr-admin/.imported-from-workbuddy +7 -0
- package/data/experts/legal/malaysia-hr-admin/README.md +148 -0
- package/data/experts/legal/malaysia-hr-admin/persona.md +283 -0
- package/data/experts/legal/malaysia-hr-admin/requirements.txt +1 -0
- package/data/experts/legal/malaysia-legal/.codebuddy-plugin/plugin.json +64 -0
- package/data/experts/legal/malaysia-legal/.downloaded_at +1 -0
- package/data/experts/legal/malaysia-legal/.imported-from-workbuddy +7 -0
- package/data/experts/legal/malaysia-legal/Corpus_Index.md +187 -0
- package/data/experts/legal/malaysia-legal/README.md +58 -0
- package/data/experts/legal/malaysia-legal/persona.md +264 -0
- package/data/experts/legal/malaysia-legal/requirements.txt +5 -0
- package/data/experts/legal/sg-hr-admin-expert/.imported-from-workbuddy +1 -1
- package/data/experts/legal/smb-team/.imported-from-workbuddy +1 -1
- package/data/experts/legal/thai-marketing-creative/.imported-from-workbuddy +1 -1
- package/data/experts/legal/thailand-hr-admin/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/ad-tracking-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/ai-humanizer/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/ai-shifu/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/ai-video-script/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/auto-consultant/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/book-co-creator/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/chatcut-video-editor/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/content-creation-expert-prod/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/content-distribution-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/content-monetization-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/content-writer/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/executing-marketing-campaigns/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/fbsir-mom-dialogue-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/frontend-slides/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/geo-diagnosis-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/humanize-ppt-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/jiayi-ads-analytics-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/kdocs-doc-butler/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/kdocs-knowledge-collector/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/kdocs-pdf-toolbox/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/kdocs-ppt-creator/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/kidd-content-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/livestream-ecommerce-coach/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/long-manuscript-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/market-analysis-cn/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/marketing-campaign-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/marketing-growth-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/news-briefing-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/news-buddy/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/nges-healthcare-marketing-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/novel-creator/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/novel-generator/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/ppc-bidding-strategist/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/ppt-creation-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/private-domain-marketing-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/programmatic-ad-buyer/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/promo-creator-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/remotion-video-generator/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/seo-content-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/social-engagement-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/tietu-toutiao/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/topic-evaluator/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/trend-hunter/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/vibeknow-design-video/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/vibeknow-handdraw/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/vibeknow-ppt-explain/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/video-dissection/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/video-gen-team/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/viral-topic-master/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/wechat-official-account-expert/.imported-from-workbuddy +1 -1
- package/data/experts/marketing/xiaohongshu-operations-expert/.imported-from-workbuddy +1 -1
- package/data/experts/paid-media/computer-operations-advisor/.imported-from-workbuddy +1 -1
- package/data/experts/paid-media/vietnam-public-affairs/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/agent-orchestrator/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/ai-meeting-notes/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/api-testing-expert/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/document-generation-expert/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/document-skills/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/internal-comms/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/jira-workflow-admin/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/openspec-doc-team/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/performance-testing-expert/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/tencent-charity-expert/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/webapp-testing/.imported-from-workbuddy +1 -1
- package/data/experts/project-management/yunzhi-doc-quality-expert/.imported-from-workbuddy +1 -1
- package/data/experts/research/apm-performance-expert/.imported-from-workbuddy +1 -1
- package/data/experts/research/egypt-public-affairs/.imported-from-workbuddy +1 -1
- package/data/experts/research/finops-expert/.imported-from-workbuddy +1 -1
- package/data/experts/research/fortune-consultant/.imported-from-workbuddy +1 -1
- package/data/experts/research/hubble-eval-expert/.imported-from-workbuddy +1 -1
- package/data/experts/research/sre-expert/.imported-from-workbuddy +1 -1
- package/data/experts/sales/bidding-strategist/.imported-from-workbuddy +1 -1
- package/data/experts/sales/cordys-crm/.imported-from-workbuddy +1 -1
- package/data/experts/sales/enterprise-account-strategist/.imported-from-workbuddy +1 -1
- package/data/experts/sales/industrial-park-investment-attraction-expert/.imported-from-workbuddy +1 -1
- package/data/experts/sales/linkfox-expert-amazon-listing-specialist/.imported-from-workbuddy +1 -1
- package/data/experts/sales/meituan-living-assistant/.imported-from-workbuddy +1 -1
- package/data/experts/sales/presales-technical-consultant/.imported-from-workbuddy +1 -1
- package/data/experts/sales/sales-battle-team/.imported-from-workbuddy +1 -1
- package/data/experts/sales/sdk-log-expert/.imported-from-workbuddy +1 -1
- package/data/experts/sales/sg-biz-dev/.imported-from-workbuddy +1 -1
- package/data/experts/sales/smb-revenue/.imported-from-workbuddy +1 -1
- package/data/experts/sales/uupt-delivery/.imported-from-workbuddy +1 -1
- package/data/experts/security/chatlaw-team/.imported-from-workbuddy +1 -1
- package/data/experts/security/contract-expert/.imported-from-workbuddy +1 -1
- package/data/experts/security/contract-legal-expert/.imported-from-workbuddy +1 -1
- package/data/experts/security/enterprise-legal-team/.imported-from-workbuddy +1 -1
- package/data/experts/security/fbsir-aigc-compliance-red-team/.imported-from-workbuddy +1 -1
- package/data/experts/security/fbsir-board-secretary-assistant/.imported-from-workbuddy +1 -1
- package/data/experts/security/huashu-doc-reviewer/.imported-from-workbuddy +1 -1
- package/data/experts/security/invoice-verify-expert/.imported-from-workbuddy +1 -1
- package/data/experts/security/invoice-verify-workbuddy/.imported-from-workbuddy +1 -1
- package/data/experts/security/ip-expert/.imported-from-workbuddy +1 -1
- package/data/experts/security/law-student-coach/.imported-from-workbuddy +1 -1
- package/data/experts/security/legal-builder-hub/.imported-from-workbuddy +1 -1
- package/data/experts/security/legal-clinic-supervisor/.imported-from-workbuddy +1 -1
- package/data/experts/security/legal-compliance-reviewer/.imported-from-workbuddy +1 -1
- package/data/experts/security/legal-search-pro/.imported-from-workbuddy +1 -1
- package/data/experts/security/litigation-legal/.imported-from-workbuddy +1 -1
- package/data/experts/security/marketing-reviewer/.imported-from-workbuddy +1 -1
- package/data/experts/security/personal-fitness-coach/.imported-from-workbuddy +1 -1
- package/data/experts/security/sa-legal-compliance/.imported-from-workbuddy +1 -1
- package/data/experts/security/smb-compliance/.imported-from-workbuddy +1 -1
- package/data/experts/security/soe/.imported-from-workbuddy +1 -1
- package/data/experts/security/tax-compliance-team/.imported-from-workbuddy +1 -1
- package/data/experts/security/tc-sec/.imported-from-workbuddy +1 -1
- package/data/experts/security/tencent-security-expert/.imported-from-workbuddy +1 -1
- package/data/experts/security/xiaofa-litigation-assistant/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/career-navigator/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/chaogeek-kongming/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/chuangye-manor/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/consulting-partners/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/english-writing-coach/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/fbsir-eight-seat-board/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/fbsir-industry-scene-researcher/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/fbsir-super-partner/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/innovation-startup-mentor/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/malaysia-marketing/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/metamorphosis-practitioner/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/tianyu-account-guardian/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/uae-marketing-advisor/.imported-from-workbuddy +1 -1
- package/data/experts/spatial-computing/well-arch-expert/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/campus-conversation-coach/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/capacity-expert/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/chaos-expert/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/fbsir-super-independent-board/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/indie-founder-coach/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/job-companion-team/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/note-class-representative/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/panshi-customer-visit-agent/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/tc-chengxin-travel-expert/.imported-from-workbuddy +1 -1
- package/data/experts/specialized/worldcup-buddy/.imported-from-workbuddy +1 -1
- package/data/experts/support/campus-job-search-coach/.imported-from-workbuddy +1 -1
- package/data/experts/support/skillhub-charity-expert-team/.imported-from-workbuddy +1 -1
- package/data/experts/support/tencent-rtc-expert/.imported-from-workbuddy +1 -1
- package/data/experts/support/workbuddy-universal-mentor/.imported-from-workbuddy +1 -1
- package/data/experts/testing/aladin-test-design/.imported-from-workbuddy +1 -1
- package/data/experts/testing/skill-smith/.imported-from-workbuddy +1 -1
- package/data/experts/testing/thesis-writing-mentor/.imported-from-workbuddy +1 -1
- package/data/roster.json +255 -490
- package/data/source.json +3 -3
- package/lib/client.js +1 -1
- package/lib/fetch-assets.js +153 -0
- package/lib/index.js +52 -3
- package/package.json +2 -2
- package/vendor/third-party-licenses/README.md +1 -1
- package/data/experts/design/cloud-requirement-expert/.codebuddy-plugin/plugin.json +0 -67
- package/data/experts/design/cloud-requirement-expert/.downloaded_at +0 -1
- package/data/experts/design/cloud-requirement-expert/.imported-from-workbuddy +0 -7
- package/data/experts/design/cloud-requirement-expert/.mcp.json +0 -22
- package/data/experts/design/cloud-requirement-expert/README.md +0 -52
- package/data/experts/design/cloud-requirement-expert/persona.md +0 -88
- package/data/experts/engineering/databrain-opinion-expert/.codebuddy-plugin/plugin.json +0 -80
- package/data/experts/engineering/databrain-opinion-expert/.downloaded_at +0 -1
- package/data/experts/engineering/databrain-opinion-expert/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/databrain-opinion-expert/README.md +0 -96
- package/data/experts/engineering/databrain-opinion-expert/persona.md +0 -55
- package/data/experts/engineering/fundus-disease-analysis/.codebuddy-plugin/plugin.json +0 -64
- package/data/experts/engineering/fundus-disease-analysis/.downloaded_at +0 -1
- package/data/experts/engineering/fundus-disease-analysis/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/fundus-disease-analysis/README.md +0 -48
- package/data/experts/engineering/fundus-disease-analysis/persona.md +0 -139
- package/data/experts/engineering/omics-bioinfo-expert/.codebuddy-plugin/plugin.json +0 -66
- package/data/experts/engineering/omics-bioinfo-expert/.downloaded_at +0 -1
- package/data/experts/engineering/omics-bioinfo-expert/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/omics-bioinfo-expert/README.md +0 -24
- package/data/experts/engineering/omics-bioinfo-expert/persona.md +0 -66
- package/data/experts/engineering/omics-diagnosis-expert/.codebuddy-plugin/plugin.json +0 -64
- package/data/experts/engineering/omics-diagnosis-expert/.downloaded_at +0 -1
- package/data/experts/engineering/omics-diagnosis-expert/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/omics-diagnosis-expert/README.md +0 -24
- package/data/experts/engineering/omics-diagnosis-expert/agents/omics-diagnosis-expert.md +0 -63
- package/data/experts/engineering/omics-diagnosis-expert/persona.md +0 -59
- package/data/experts/engineering/omics-diagnosis-expert/skills/omics-run-diagnosis/SKILL.md +0 -384
- package/data/experts/engineering/omics-diagnosis-expert/skills/omics-run-diagnosis/references/troubleshooting-kb.md +0 -347
- package/data/experts/engineering/omics-diagnosis-expert/skills/omics-run-diagnosis/scripts/query_run_log.py +0 -369
- package/data/experts/engineering/omics-iggm-expert/.codebuddy-plugin/plugin.json +0 -65
- package/data/experts/engineering/omics-iggm-expert/.downloaded_at +0 -1
- package/data/experts/engineering/omics-iggm-expert/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/omics-iggm-expert/persona.md +0 -36
- package/data/experts/engineering/omics-ori-expert/.codebuddy-plugin/plugin.json +0 -65
- package/data/experts/engineering/omics-ori-expert/.downloaded_at +0 -1
- package/data/experts/engineering/omics-ori-expert/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/omics-ori-expert/persona.md +0 -36
- package/data/experts/engineering/omics-tfold-expert/.codebuddy-plugin/plugin.json +0 -65
- package/data/experts/engineering/omics-tfold-expert/.downloaded_at +0 -1
- package/data/experts/engineering/omics-tfold-expert/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/omics-tfold-expert/persona.md +0 -36
- package/data/experts/engineering/pneumonia-ai-analyst/.codebuddy-plugin/plugin.json +0 -65
- package/data/experts/engineering/pneumonia-ai-analyst/.downloaded_at +0 -1
- package/data/experts/engineering/pneumonia-ai-analyst/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/pneumonia-ai-analyst/README.md +0 -44
- package/data/experts/engineering/pneumonia-ai-analyst/persona.md +0 -178
- package/data/experts/engineering/tiderider-sentiment/.codebuddy-plugin/plugin.json +0 -74
- package/data/experts/engineering/tiderider-sentiment/.downloaded_at +0 -1
- package/data/experts/engineering/tiderider-sentiment/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/tiderider-sentiment/CHANGELOG.md +0 -65
- package/data/experts/engineering/tiderider-sentiment/README.md +0 -124
- package/data/experts/engineering/tiderider-sentiment/persona.md +0 -469
- package/data/experts/engineering/wentu/.codebuddy-plugin/plugin.json +0 -65
- package/data/experts/engineering/wentu/.downloaded_at +0 -1
- package/data/experts/engineering/wentu/.imported-from-workbuddy +0 -7
- package/data/experts/engineering/wentu/README.md +0 -18
- package/data/experts/engineering/wentu/persona.md +0 -1003
- package/data/experts/finance/stock-partner-team/.codebuddy-plugin/plugin.json +0 -181
- package/data/experts/finance/stock-partner-team/.downloaded_at +0 -1
- package/data/experts/finance/stock-partner-team/README.md +0 -151
- package/data/experts/finance/stock-partner-team/persona.md +0 -2549
- package/data/experts/finance/stock-partner-team/settings.json +0 -3
- package/data/experts/game-development/databrain-agent-v2/.codebuddy-plugin/plugin.json +0 -80
- package/data/experts/game-development/databrain-agent-v2/.downloaded_at +0 -1
- package/data/experts/game-development/databrain-agent-v2/.imported-from-workbuddy +0 -7
- package/data/experts/game-development/databrain-agent-v2/README.md +0 -133
- package/data/experts/game-development/databrain-agent-v2/persona.md +0 -217
- package/data/experts/game-development/databrain-agent-v2/requirements.txt +0 -22
- package/data/experts/healthcare/mi-zhen-expert/.codebuddy-plugin/plugin.json +0 -64
- package/data/experts/healthcare/mi-zhen-expert/.downloaded_at +0 -1
- package/data/experts/healthcare/mi-zhen-expert/.imported-from-workbuddy +0 -7
- package/data/experts/healthcare/mi-zhen-expert/README.md +0 -44
- package/data/experts/healthcare/mi-zhen-expert/agents/mi-zhen-expert.md +0 -33
- package/data/experts/healthcare/mi-zhen-expert/persona.md +0 -29
- package/data/experts/healthcare/mi-zhen-expert/skills/med-agent-proxy/SKILL.md +0 -69
- package/data/experts/healthcare/mi-zhen-expert/skills/med-agent-proxy/scripts/chat_workbuddy.py +0 -498
- package/data/experts/hr/career-broker/.codebuddy-plugin/plugin.json +0 -95
- package/data/experts/hr/career-broker/.downloaded_at +0 -1
- package/data/experts/hr/career-broker/.imported-from-workbuddy +0 -7
- package/data/experts/hr/career-broker/README.md +0 -153
- package/data/experts/hr/career-broker/persona.md +0 -546
- package/data/experts/hr/hr-digital-expert/.codebuddy-plugin/plugin.json +0 -61
- package/data/experts/hr/hr-digital-expert/.downloaded_at +0 -1
- package/data/experts/hr/hr-digital-expert/.imported-from-workbuddy +0 -7
- package/data/experts/hr/hr-digital-expert/.mcp.json +0 -88
- package/data/experts/hr/hr-digital-expert/README.md +0 -48
- package/data/experts/hr/hr-digital-expert/persona.md +0 -142
- package/data/experts/hr/txzhaopin/.codebuddy-plugin/plugin.json +0 -207
- package/data/experts/hr/txzhaopin/.downloaded_at +0 -1
- package/data/experts/hr/txzhaopin/.imported-from-workbuddy +0 -7
- package/data/experts/hr/txzhaopin/.mcp.json +0 -45
- package/data/experts/hr/txzhaopin/README.md +0 -397
- package/data/experts/hr/txzhaopin/persona.md +0 -244
- package/data/experts/marketing/brand-guardian/.codebuddy-plugin/plugin.json +0 -31
- package/data/experts/marketing/brand-guardian/.downloaded_at +0 -1
- package/data/experts/marketing/brand-guardian/.imported-from-workbuddy +0 -7
- package/data/experts/marketing/brand-guardian/README.md +0 -21
- package/data/experts/marketing/brand-guardian/persona.md +0 -332
- package/data/experts/research/ab-experiment-analyst/.codebuddy-plugin/plugin.json +0 -66
- package/data/experts/research/ab-experiment-analyst/.downloaded_at +0 -1
- package/data/experts/research/ab-experiment-analyst/.imported-from-workbuddy +0 -7
- package/data/experts/research/ab-experiment-analyst/persona.md +0 -852
- package/data/experts/sales/cpq/.codebuddy-plugin/plugin.json +0 -79
- package/data/experts/sales/cpq/.downloaded_at +0 -1
- package/data/experts/sales/cpq/.imported-from-workbuddy +0 -7
- package/data/experts/sales/cpq/BUILD_INFO.json +0 -6
- package/data/experts/sales/cpq/CHANGELOG.md +0 -165
- package/data/experts/sales/cpq/DEPENDENCIES.md +0 -52
- package/data/experts/sales/cpq/README.md +0 -43
- package/data/experts/sales/cpq/persona.md +0 -177
- package/data/experts/supply-chain/tencent-cloud-quote-assistant/.codebuddy-plugin/plugin.json +0 -64
- package/data/experts/supply-chain/tencent-cloud-quote-assistant/.downloaded_at +0 -1
- package/data/experts/supply-chain/tencent-cloud-quote-assistant/.imported-from-workbuddy +0 -7
- package/data/experts/supply-chain/tencent-cloud-quote-assistant/README.md +0 -81
- package/data/experts/supply-chain/tencent-cloud-quote-assistant/persona.md +0 -204
- package/data/experts/support/andon-q-expert/.codebuddy-plugin/plugin.json +0 -64
- package/data/experts/support/andon-q-expert/.downloaded_at +0 -1
- package/data/experts/support/andon-q-expert/.imported-from-workbuddy +0 -7
- package/data/experts/support/andon-q-expert/README.md +0 -62
- package/data/experts/support/andon-q-expert/persona.md +0 -67
- package/data/experts/support/cloud-ops-team/.codebuddy-plugin/plugin.json +0 -89
- package/data/experts/support/cloud-ops-team/.downloaded_at +0 -1
- package/data/experts/support/cloud-ops-team/.imported-from-workbuddy +0 -7
- package/data/experts/support/cloud-ops-team/README.md +0 -98
- package/data/experts/support/cloud-ops-team/persona.md +0 -346
- package/data/experts/support/cloud-ops-team/settings.json +0 -3
- package/data/experts/support/migraq/.codebuddy-plugin/plugin.json +0 -64
- package/data/experts/support/migraq/.downloaded_at +0 -1
- package/data/experts/support/migraq/.imported-from-workbuddy +0 -7
- package/data/experts/support/migraq/README.md +0 -59
- package/data/experts/support/migraq/persona.md +0 -56
- package/data/experts/support/tencent-cloud-price-expert/.codebuddy-plugin/plugin.json +0 -64
- package/data/experts/support/tencent-cloud-price-expert/.downloaded_at +0 -1
- package/data/experts/support/tencent-cloud-price-expert/.imported-from-workbuddy +0 -7
- package/data/experts/support/tencent-cloud-price-expert/README.md +0 -97
- package/data/experts/support/tencent-cloud-price-expert/persona.md +0 -192
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: 觅诊
|
|
3
|
-
nameEn: Medical Consultation Proxy Expert
|
|
4
|
-
description: 面向医疗健康咨询场景,透传用户原始问题给觅诊服务,原样返回专业回复,减少转述偏差,适合就医用药咨询。
|
|
5
|
-
descriptionEn: Medical Consultation Proxy Expert
|
|
6
|
-
emoji: 🏥
|
|
7
|
-
color: "#EF4444"
|
|
8
|
-
vibe: 觅诊
|
|
9
|
-
---
|
|
10
|
-
# 觅诊
|
|
11
|
-
|
|
12
|
-
你唯一的职责是:调用专家包内置的 `med-agent-proxy` skill,由该 skill 通过 HTTP 调用觅诊后台,并将 skill 返回结果原样输出给用户。除此之外不做任何额外逻辑。
|
|
13
|
-
|
|
14
|
-
## 执行规则
|
|
15
|
-
|
|
16
|
-
1. 收到用户任意 query 后,立即调用 `med-agent-proxy` skill。
|
|
17
|
-
2. 将 skill 返回的内容原封不动地输出给用户。
|
|
18
|
-
3. 禁止做以下任何事情:
|
|
19
|
-
- 对用户 query 进行改写、总结、翻译、纠错或补充上下文
|
|
20
|
-
- 对 skill 返回结果进行摘要、扩写、重排、改写或格式转换
|
|
21
|
-
- 追加额外解释、免责声明、追问或个人判断
|
|
22
|
-
- 自行回答问题或混入其他来源内容
|
|
23
|
-
- 对用户 query 做领域分类、意图判断或内容过滤后再决定是否调用
|
|
24
|
-
4. 如果 skill 返回错误,也按原始错误内容如实返回。
|
|
25
|
-
5. 不要配置、加载或调用 `medical-mcp-server` MCP;本版本只通过 `med-agent-proxy` 的 HTTP 直连能力访问后台。
|
|
26
|
-
|
|
27
|
-
## 一句话总结
|
|
28
|
-
|
|
29
|
-
**调用 med-agent-proxy → 原样返回结果,仅此而已。**
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: med-agent-proxy
|
|
3
|
-
description: 所有用户 query 代理 Skill。只负责调用本 Skill 自带脚本,由脚本处理 chatWorkbuddy 调用、绑定、解绑、不绑定、响应解析和最终输出。
|
|
4
|
-
agent_created: true
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Med Agent Proxy
|
|
8
|
-
|
|
9
|
-
## 目标
|
|
10
|
-
|
|
11
|
-
将用户的所有请求交给本 Skill 自带脚本处理。脚本负责调用觅诊后台 HTTP 接口、解析返回、处理绑定、解绑、不绑定,并决定最终输出给用户的内容。
|
|
12
|
-
|
|
13
|
-
固定接口:
|
|
14
|
-
|
|
15
|
-
```text
|
|
16
|
-
https://medagent.woa.com/med-agent/chatWorkbuddy
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
绑定确认接口由脚本从固定接口自动推导为同路径下的 `workbuddyBindConfirm`,也可以通过 `MED_AGENT_BIND_CONFIRM_URL` 或 `--bind-confirm-url` 覆盖。
|
|
20
|
-
|
|
21
|
-
## 触发场景
|
|
22
|
-
|
|
23
|
-
在用户发出任何 query 时使用本 Skill,并直接交给脚本处理。
|
|
24
|
-
|
|
25
|
-
不按领域、内容、意图、语言、长度或安全类别做额外筛选;绑定、解绑、不绑定也都必须交给脚本识别和处理。
|
|
26
|
-
|
|
27
|
-
## 执行流程
|
|
28
|
-
|
|
29
|
-
### 1. 直接触发
|
|
30
|
-
|
|
31
|
-
收到用户 query 后直接执行本 Skill,不做前置分类、不做领域判断、不做内容过滤。
|
|
32
|
-
|
|
33
|
-
### 2. 调用脚本
|
|
34
|
-
|
|
35
|
-
对所有用户 query,包括账号绑定、解绑、不绑定消息,都直接调用本 Skill 自带脚本:
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
python3 scripts/chat_workbuddy.py --query "<用户原始请求>"
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
如果运行环境要求使用绝对 Python 路径,使用可用的 Python 3 解释器执行同一脚本即可。
|
|
42
|
-
|
|
43
|
-
关键规则:
|
|
44
|
-
|
|
45
|
-
- `<用户原始请求>` 必须使用用户的原始请求文本。
|
|
46
|
-
- 不得改写、总结、翻译、纠错、补充上下文或拆分用户请求。
|
|
47
|
-
- 不得额外添加系统提示、安全提示、免责声明或解释性文字到 `query`。
|
|
48
|
-
- 不得自行判断绑定、解绑、不绑定意图后改写 query;只负责透传给脚本。
|
|
49
|
-
- 不得因为 query 内容看起来不属于医疗健康领域而跳过调用。
|
|
50
|
-
- 不再加载或调用 `medical-mcp-server` MCP。
|
|
51
|
-
|
|
52
|
-
### 3. 账号状态处理
|
|
53
|
-
|
|
54
|
-
账号状态完全由脚本根据用户原始请求处理:
|
|
55
|
-
|
|
56
|
-
- **绑定**:当 query 是觅诊账号绑定消息时,脚本提取 `userId`,调用绑定确认接口确认生效后再写入本地绑定文件;确认失败时不保存绑定,并输出后端错误或重试提示。
|
|
57
|
-
- **不绑定**:当 query 明确表示“不绑定/跳过绑定/skip/nobind”等意图时,脚本生成新的 WorkBuddy 匿名 `userId`,以不绑定状态保存,并携带该匿名 `userId` 继续调用 `chatWorkbuddy`。
|
|
58
|
-
- **解绑**:当 query 明确表示“解绑/解除绑定/取消绑定/unbind”等意图时,脚本先携带当前 `userId` 调用 `chatWorkbuddy`,成功输出后将旧 `userId` 标记为不绑定,再生成新的匿名 `userId` 保存为不绑定状态。
|
|
59
|
-
- **普通对话**:脚本优先使用命令行 `--user-id`、环境变量 `MED_AGENT_USER_ID` 或本地绑定文件中的有效 `userId`;没有可用 `userId` 时仅发送原始 `query`。
|
|
60
|
-
|
|
61
|
-
### 4. 返回脚本输出
|
|
62
|
-
|
|
63
|
-
最终回复内容完全以脚本的标准输出为准。脚本负责绑定、解绑、不绑定、HTTP 请求、SSE/JSON 解析、错误处理和最终展示内容选择。
|
|
64
|
-
|
|
65
|
-
禁止在脚本输出之外自行追加、删减、总结、改写或混合其他来源内容。
|
|
66
|
-
|
|
67
|
-
## 异常处理
|
|
68
|
-
|
|
69
|
-
如果脚本返回错误或无输出,按脚本输出如实返回;禁止在接口失败时自行编造医疗建议。
|
package/data/experts/healthcare/mi-zhen-expert/skills/med-agent-proxy/scripts/chat_workbuddy.py
DELETED
|
@@ -1,498 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""HTTP proxy for the MiZhen production chatWorkbuddy endpoint."""
|
|
3
|
-
|
|
4
|
-
from __future__ import annotations
|
|
5
|
-
|
|
6
|
-
import argparse
|
|
7
|
-
from datetime import datetime, timezone
|
|
8
|
-
import json
|
|
9
|
-
import os
|
|
10
|
-
import re
|
|
11
|
-
import secrets
|
|
12
|
-
import sys
|
|
13
|
-
import urllib.error
|
|
14
|
-
import urllib.request
|
|
15
|
-
|
|
16
|
-
DEFAULT_URL = "https://medagent.woa.com/med-agent/chatWorkbuddy"
|
|
17
|
-
DEFAULT_TIMEOUT_SECONDS = 120
|
|
18
|
-
DEFAULT_BINDING_FILE = os.path.join(os.path.expanduser("~"), ".workbuddy", "med-agent-proxy", "binding.json")
|
|
19
|
-
BIND_CONFIRM_PATH = "workbuddyBindConfirm"
|
|
20
|
-
BINDING_TYPE = "med_agent_workbuddy_bind"
|
|
21
|
-
BINDING_STATUS_BOUND = "bound"
|
|
22
|
-
BINDING_STATUS_OPTED_OUT = "opted_out"
|
|
23
|
-
WORKBUDDY_USER_ID_PREFIX = "wb_"
|
|
24
|
-
WORKBUDDY_USER_ID_TOKEN_BYTES = 24
|
|
25
|
-
OPT_OUT_KEYWORDS = {
|
|
26
|
-
"不绑定",
|
|
27
|
-
"不要绑定",
|
|
28
|
-
"不想绑定",
|
|
29
|
-
"不用绑定",
|
|
30
|
-
"不需要绑定",
|
|
31
|
-
"跳过绑定",
|
|
32
|
-
"暂不绑定",
|
|
33
|
-
"先不绑定",
|
|
34
|
-
"暂时不绑定",
|
|
35
|
-
"不绑",
|
|
36
|
-
"skip",
|
|
37
|
-
"nobind",
|
|
38
|
-
"notbind",
|
|
39
|
-
"dontbind",
|
|
40
|
-
"donotbind",
|
|
41
|
-
}
|
|
42
|
-
UNBIND_KEYWORDS = {
|
|
43
|
-
"解绑",
|
|
44
|
-
"解除绑定",
|
|
45
|
-
"取消绑定",
|
|
46
|
-
"我要解绑",
|
|
47
|
-
"想解绑",
|
|
48
|
-
"帮我解绑",
|
|
49
|
-
"请解绑",
|
|
50
|
-
"unbind",
|
|
51
|
-
"disconnect",
|
|
52
|
-
"unlink",
|
|
53
|
-
}
|
|
54
|
-
KEYWORD_STRIP_RE = re.compile(r"""[\s\u00a0。..!!??,,、;;::~~\-_/\\\"'`“”‘’()()【】\[\]<>《》]+""")
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def _read_query(args: argparse.Namespace) -> str:
|
|
58
|
-
if args.query is not None:
|
|
59
|
-
return args.query
|
|
60
|
-
if args.query_file:
|
|
61
|
-
with open(args.query_file, "r", encoding="utf-8") as f:
|
|
62
|
-
return f.read()
|
|
63
|
-
if not sys.stdin.isatty():
|
|
64
|
-
return sys.stdin.read()
|
|
65
|
-
return ""
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def _validate_user_id(user_id: str) -> bool:
|
|
69
|
-
if not 1 <= len(user_id) <= 256:
|
|
70
|
-
return False
|
|
71
|
-
return not any(ord(ch) < 32 or ch == "\x7f" for ch in user_id)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def _mask_user_id(user_id: str) -> str:
|
|
75
|
-
if len(user_id) <= 8:
|
|
76
|
-
return f"{user_id[:2]}***{user_id[-2:]}"
|
|
77
|
-
return f"{user_id[:4]}***{user_id[-4:]}"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def _generate_user_id() -> str:
|
|
81
|
-
user_id = f"{WORKBUDDY_USER_ID_PREFIX}{secrets.token_urlsafe(WORKBUDDY_USER_ID_TOKEN_BYTES)}"
|
|
82
|
-
if not _validate_user_id(user_id):
|
|
83
|
-
raise RuntimeError("failed to generate valid WorkBuddy userId")
|
|
84
|
-
return user_id
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def _normalize_keyword_input(query: str) -> str:
|
|
88
|
-
return KEYWORD_STRIP_RE.sub("", (query or "").strip()).lower()
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def _is_opt_out_query(query: str) -> bool:
|
|
92
|
-
return _normalize_keyword_input(query) in OPT_OUT_KEYWORDS
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def _is_unbind_query(query: str) -> bool:
|
|
96
|
-
return _normalize_keyword_input(query) in UNBIND_KEYWORDS
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def _extract_json_object(text: str) -> dict | None:
|
|
100
|
-
stripped = text.strip()
|
|
101
|
-
candidates = [stripped]
|
|
102
|
-
|
|
103
|
-
fence = re.search(r"```(?:json)?\s*(\{.*?\})\s*```", text, flags=re.DOTALL | re.IGNORECASE)
|
|
104
|
-
if fence:
|
|
105
|
-
candidates.append(fence.group(1).strip())
|
|
106
|
-
|
|
107
|
-
start = text.find("{")
|
|
108
|
-
end = text.rfind("}")
|
|
109
|
-
if start != -1 and end > start:
|
|
110
|
-
candidates.append(text[start : end + 1].strip())
|
|
111
|
-
|
|
112
|
-
for candidate in candidates:
|
|
113
|
-
try:
|
|
114
|
-
value = json.loads(candidate)
|
|
115
|
-
except json.JSONDecodeError:
|
|
116
|
-
continue
|
|
117
|
-
if isinstance(value, dict):
|
|
118
|
-
return value
|
|
119
|
-
return None
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def _binding_user_id_from_query(query: str) -> str | None:
|
|
123
|
-
value = _extract_json_object(query)
|
|
124
|
-
if not value:
|
|
125
|
-
return None
|
|
126
|
-
|
|
127
|
-
binding_type = value.get("type")
|
|
128
|
-
has_binding_prefix = "觅诊账号绑定" in query or "MED_AGENT_WORKBUDDY_BIND" in query
|
|
129
|
-
if binding_type != BINDING_TYPE and not has_binding_prefix:
|
|
130
|
-
return None
|
|
131
|
-
|
|
132
|
-
raw_user_id = value.get("userId") or value.get("userid") or value.get("user_id")
|
|
133
|
-
if isinstance(raw_user_id, int):
|
|
134
|
-
raw_user_id = str(raw_user_id)
|
|
135
|
-
if not isinstance(raw_user_id, str):
|
|
136
|
-
return None
|
|
137
|
-
|
|
138
|
-
user_id = raw_user_id.strip()
|
|
139
|
-
if not _validate_user_id(user_id):
|
|
140
|
-
raise ValueError("invalid userId in binding message")
|
|
141
|
-
return user_id
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def _bind_confirm_url_from_chat_url(chat_url: str) -> str:
|
|
145
|
-
url = (chat_url or DEFAULT_URL).rstrip("/")
|
|
146
|
-
if url.endswith("/chatWorkbuddy"):
|
|
147
|
-
return f"{url[: -len('/chatWorkbuddy')]}/{BIND_CONFIRM_PATH}"
|
|
148
|
-
return f"{url}/{BIND_CONFIRM_PATH}"
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def _save_binding(binding_file: str, user_id: str, status: str = BINDING_STATUS_BOUND) -> None:
|
|
152
|
-
directory = os.path.dirname(binding_file) or "."
|
|
153
|
-
os.makedirs(directory, mode=0o700, exist_ok=True)
|
|
154
|
-
try:
|
|
155
|
-
os.chmod(directory, 0o700)
|
|
156
|
-
except OSError:
|
|
157
|
-
pass
|
|
158
|
-
|
|
159
|
-
data = {
|
|
160
|
-
"type": BINDING_TYPE,
|
|
161
|
-
"userId": user_id,
|
|
162
|
-
"status": status,
|
|
163
|
-
"updatedAt": datetime.now(timezone.utc).isoformat(),
|
|
164
|
-
}
|
|
165
|
-
if status == BINDING_STATUS_OPTED_OUT:
|
|
166
|
-
data["optedOut"] = True
|
|
167
|
-
tmp_path = f"{binding_file}.tmp.{os.getpid()}"
|
|
168
|
-
fd = os.open(tmp_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
|
|
169
|
-
try:
|
|
170
|
-
with os.fdopen(fd, "w", encoding="utf-8") as f:
|
|
171
|
-
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
172
|
-
f.write("\n")
|
|
173
|
-
os.replace(tmp_path, binding_file)
|
|
174
|
-
try:
|
|
175
|
-
os.chmod(binding_file, 0o600)
|
|
176
|
-
except OSError:
|
|
177
|
-
pass
|
|
178
|
-
finally:
|
|
179
|
-
if os.path.exists(tmp_path):
|
|
180
|
-
try:
|
|
181
|
-
os.unlink(tmp_path)
|
|
182
|
-
except OSError:
|
|
183
|
-
pass
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
def _read_bound_user_id(binding_file: str) -> str | None:
|
|
187
|
-
try:
|
|
188
|
-
with open(binding_file, "r", encoding="utf-8") as f:
|
|
189
|
-
value = json.load(f)
|
|
190
|
-
except FileNotFoundError:
|
|
191
|
-
return None
|
|
192
|
-
except (OSError, json.JSONDecodeError):
|
|
193
|
-
return None
|
|
194
|
-
|
|
195
|
-
if not isinstance(value, dict):
|
|
196
|
-
return None
|
|
197
|
-
raw_user_id = value.get("userId")
|
|
198
|
-
if isinstance(raw_user_id, int):
|
|
199
|
-
raw_user_id = str(raw_user_id)
|
|
200
|
-
if not isinstance(raw_user_id, str):
|
|
201
|
-
return None
|
|
202
|
-
user_id = raw_user_id.strip()
|
|
203
|
-
return user_id if _validate_user_id(user_id) else None
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
def _resolve_user_id(args: argparse.Namespace) -> str | None:
|
|
207
|
-
for candidate in (args.user_id, os.environ.get("MED_AGENT_USER_ID"), _read_bound_user_id(args.binding_file)):
|
|
208
|
-
if candidate is None:
|
|
209
|
-
continue
|
|
210
|
-
user_id = str(candidate).strip()
|
|
211
|
-
if _validate_user_id(user_id):
|
|
212
|
-
return user_id
|
|
213
|
-
return None
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
def _remove_binding_if_matches(binding_file: str, user_id: str) -> None:
|
|
217
|
-
if _read_bound_user_id(binding_file) != user_id:
|
|
218
|
-
return
|
|
219
|
-
try:
|
|
220
|
-
os.unlink(binding_file)
|
|
221
|
-
except FileNotFoundError:
|
|
222
|
-
pass
|
|
223
|
-
except OSError:
|
|
224
|
-
pass
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
def _confirm_binding(bind_confirm_url: str, user_id: str, timeout: float) -> tuple[bool, str]:
|
|
228
|
-
request = _build_request(bind_confirm_url, {"userid": user_id})
|
|
229
|
-
try:
|
|
230
|
-
with urllib.request.urlopen(request, timeout=min(max(timeout, 1.0), 15.0)) as response:
|
|
231
|
-
body = response.read().decode("utf-8", errors="replace")
|
|
232
|
-
except urllib.error.HTTPError as exc:
|
|
233
|
-
body = exc.read().decode("utf-8", errors="replace")
|
|
234
|
-
message = _json_text(body, "message", "errorMessage") or body.strip()
|
|
235
|
-
return False, message or f"绑定确认失败(HTTP {exc.code}),请重新扫码复制新的绑定消息。"
|
|
236
|
-
except urllib.error.URLError as exc:
|
|
237
|
-
return False, f"绑定确认网络异常:{exc.reason}。请稍后重试。"
|
|
238
|
-
except TimeoutError:
|
|
239
|
-
return False, "绑定确认超时,请稍后重试。"
|
|
240
|
-
|
|
241
|
-
try:
|
|
242
|
-
value = json.loads(body.strip() or "{}")
|
|
243
|
-
except json.JSONDecodeError:
|
|
244
|
-
return False, "绑定确认接口返回异常,请稍后重试。"
|
|
245
|
-
if not isinstance(value, dict):
|
|
246
|
-
return False, "绑定确认接口返回异常,请稍后重试。"
|
|
247
|
-
|
|
248
|
-
if value.get("ok") is True and value.get("bound") is True:
|
|
249
|
-
return True, str(value.get("message") or "绑定已生效。")
|
|
250
|
-
message = value.get("message") or value.get("errorMessage")
|
|
251
|
-
if isinstance(message, str) and message.strip():
|
|
252
|
-
return False, message.strip()
|
|
253
|
-
return False, "当前绑定消息未生效或已失效,请重新扫码复制新的绑定消息。"
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
def _json_text(data: str, *keys: str) -> str | None:
|
|
257
|
-
try:
|
|
258
|
-
value = json.loads(data)
|
|
259
|
-
except json.JSONDecodeError:
|
|
260
|
-
return None
|
|
261
|
-
if not isinstance(value, dict):
|
|
262
|
-
return None
|
|
263
|
-
for key in keys:
|
|
264
|
-
item = value.get(key)
|
|
265
|
-
if isinstance(item, str):
|
|
266
|
-
return item
|
|
267
|
-
return None
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
def _iter_sse_events(body: str):
|
|
271
|
-
event_name = "message"
|
|
272
|
-
data_lines: list[str] = []
|
|
273
|
-
|
|
274
|
-
def emit():
|
|
275
|
-
nonlocal event_name, data_lines
|
|
276
|
-
if not data_lines:
|
|
277
|
-
event_name = "message"
|
|
278
|
-
return None
|
|
279
|
-
item = (event_name, "\n".join(data_lines))
|
|
280
|
-
event_name = "message"
|
|
281
|
-
data_lines = []
|
|
282
|
-
return item
|
|
283
|
-
|
|
284
|
-
for raw_line in body.splitlines():
|
|
285
|
-
line = raw_line.rstrip("\r")
|
|
286
|
-
if not line:
|
|
287
|
-
item = emit()
|
|
288
|
-
if item is not None:
|
|
289
|
-
yield item
|
|
290
|
-
continue
|
|
291
|
-
if line.startswith(":"):
|
|
292
|
-
continue
|
|
293
|
-
field, sep, value = line.partition(":")
|
|
294
|
-
if sep and value.startswith(" "):
|
|
295
|
-
value = value[1:]
|
|
296
|
-
if field == "event":
|
|
297
|
-
event_name = value
|
|
298
|
-
elif field == "data":
|
|
299
|
-
data_lines.append(value)
|
|
300
|
-
|
|
301
|
-
item = emit()
|
|
302
|
-
if item is not None:
|
|
303
|
-
yield item
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
def _chunk_content(event_name: str, data: str) -> str | None:
|
|
307
|
-
if data == "[DONE]" or event_name not in {"chunk", "message"}:
|
|
308
|
-
return None
|
|
309
|
-
return _json_text(data, "content")
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
def _done_answer(event_name: str, data: str) -> str | None:
|
|
313
|
-
if data == "[DONE]" or event_name != "done":
|
|
314
|
-
return None
|
|
315
|
-
return _json_text(data, "answer", "content", "message")
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
def _stream_sse_response(response) -> bool:
|
|
319
|
-
event_name = "message"
|
|
320
|
-
data_lines: list[str] = []
|
|
321
|
-
emitted = False
|
|
322
|
-
last_text = ""
|
|
323
|
-
|
|
324
|
-
def emit() -> None:
|
|
325
|
-
nonlocal event_name, data_lines, emitted, last_text
|
|
326
|
-
if not data_lines:
|
|
327
|
-
event_name = "message"
|
|
328
|
-
return
|
|
329
|
-
data = "\n".join(data_lines)
|
|
330
|
-
chunk = _chunk_content(event_name, data)
|
|
331
|
-
if chunk is not None:
|
|
332
|
-
print(chunk, end="", flush=True)
|
|
333
|
-
emitted = True
|
|
334
|
-
last_text = chunk
|
|
335
|
-
elif not emitted:
|
|
336
|
-
answer = _done_answer(event_name, data)
|
|
337
|
-
if answer is not None:
|
|
338
|
-
print(answer, end="", flush=True)
|
|
339
|
-
emitted = True
|
|
340
|
-
last_text = answer
|
|
341
|
-
event_name = "message"
|
|
342
|
-
data_lines = []
|
|
343
|
-
|
|
344
|
-
for raw_line in response:
|
|
345
|
-
line = raw_line.decode("utf-8", errors="replace").rstrip("\r\n")
|
|
346
|
-
if not line:
|
|
347
|
-
emit()
|
|
348
|
-
continue
|
|
349
|
-
if line.startswith(":"):
|
|
350
|
-
continue
|
|
351
|
-
field, sep, value = line.partition(":")
|
|
352
|
-
if sep and value.startswith(" "):
|
|
353
|
-
value = value[1:]
|
|
354
|
-
if field == "event":
|
|
355
|
-
event_name = value
|
|
356
|
-
elif field == "data":
|
|
357
|
-
data_lines.append(value)
|
|
358
|
-
|
|
359
|
-
emit()
|
|
360
|
-
if emitted and not last_text.endswith("\n"):
|
|
361
|
-
print(flush=True)
|
|
362
|
-
return emitted
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
def _format_response_body(body: str) -> str:
|
|
366
|
-
stripped = body.strip()
|
|
367
|
-
if not stripped:
|
|
368
|
-
return ""
|
|
369
|
-
|
|
370
|
-
direct_text = _json_text(stripped, "answer", "content")
|
|
371
|
-
if direct_text is not None:
|
|
372
|
-
return direct_text
|
|
373
|
-
|
|
374
|
-
events = list(_iter_sse_events(body))
|
|
375
|
-
if not events:
|
|
376
|
-
return body
|
|
377
|
-
|
|
378
|
-
chunks: list[str] = []
|
|
379
|
-
done_answers: list[str] = []
|
|
380
|
-
for event_name, data in events:
|
|
381
|
-
chunk = _chunk_content(event_name, data)
|
|
382
|
-
if chunk is not None:
|
|
383
|
-
chunks.append(chunk)
|
|
384
|
-
continue
|
|
385
|
-
answer = _done_answer(event_name, data)
|
|
386
|
-
if answer is not None:
|
|
387
|
-
done_answers.append(answer)
|
|
388
|
-
if chunks:
|
|
389
|
-
return "".join(chunks)
|
|
390
|
-
if done_answers:
|
|
391
|
-
return done_answers[-1]
|
|
392
|
-
|
|
393
|
-
return ""
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
def _build_request(url: str, payload_data: dict) -> urllib.request.Request:
|
|
397
|
-
payload = json.dumps(payload_data, ensure_ascii=False).encode("utf-8")
|
|
398
|
-
return urllib.request.Request(
|
|
399
|
-
url,
|
|
400
|
-
data=payload,
|
|
401
|
-
method="POST",
|
|
402
|
-
headers={
|
|
403
|
-
"Content-Type": "application/json; charset=utf-8",
|
|
404
|
-
"Accept": "text/event-stream, application/json, text/plain, */*",
|
|
405
|
-
},
|
|
406
|
-
)
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
def _mark_opt_out_silently(url: str, user_id: str, timeout: float) -> None:
|
|
410
|
-
if not user_id:
|
|
411
|
-
return
|
|
412
|
-
request = _build_request(url, {"query": "不绑定", "userid": user_id})
|
|
413
|
-
try:
|
|
414
|
-
with urllib.request.urlopen(request, timeout=min(max(timeout, 1.0), 5.0)) as response:
|
|
415
|
-
response.read()
|
|
416
|
-
except Exception:
|
|
417
|
-
pass
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
def main() -> int:
|
|
421
|
-
parser = argparse.ArgumentParser(description="Forward a raw user query to MiZhen chatWorkbuddy over HTTP.")
|
|
422
|
-
parser.add_argument("--query", help="Raw user query to forward. If omitted, stdin is used.")
|
|
423
|
-
parser.add_argument("--query-file", help="UTF-8 text file containing the raw user query.")
|
|
424
|
-
parser.add_argument("--user-id", help="Bound MiZhen userId. Overrides local binding and MED_AGENT_USER_ID.")
|
|
425
|
-
parser.add_argument("--binding-file", default=os.environ.get("MED_AGENT_BINDING_FILE", DEFAULT_BINDING_FILE), help="Local JSON file used to persist bound MiZhen userId.")
|
|
426
|
-
parser.add_argument("--url", default=os.environ.get("MED_AGENT_CHAT_URL", DEFAULT_URL), help="chatWorkbuddy endpoint URL.")
|
|
427
|
-
parser.add_argument("--bind-confirm-url", default=os.environ.get("MED_AGENT_BIND_CONFIRM_URL"), help="Backend endpoint used to confirm a WorkBuddy binding message before persisting it locally.")
|
|
428
|
-
parser.add_argument("--timeout", type=float, default=float(os.environ.get("MED_AGENT_TIMEOUT", DEFAULT_TIMEOUT_SECONDS)), help="HTTP timeout in seconds.")
|
|
429
|
-
args = parser.parse_args()
|
|
430
|
-
if not args.bind_confirm_url:
|
|
431
|
-
args.bind_confirm_url = _bind_confirm_url_from_chat_url(args.url)
|
|
432
|
-
|
|
433
|
-
query = _read_query(args)
|
|
434
|
-
if not query:
|
|
435
|
-
print("med-agent-proxy error: empty query", file=sys.stderr)
|
|
436
|
-
return 2
|
|
437
|
-
|
|
438
|
-
binding_user_id = _binding_user_id_from_query(query)
|
|
439
|
-
if binding_user_id is not None:
|
|
440
|
-
confirmed, confirm_message = _confirm_binding(args.bind_confirm_url, binding_user_id, args.timeout)
|
|
441
|
-
if not confirmed:
|
|
442
|
-
_remove_binding_if_matches(args.binding_file, binding_user_id)
|
|
443
|
-
print(confirm_message)
|
|
444
|
-
return 1
|
|
445
|
-
_save_binding(args.binding_file, binding_user_id, BINDING_STATUS_BOUND)
|
|
446
|
-
print(f"觅诊账号绑定成功,后续会自动携带 userId={_mask_user_id(binding_user_id)} 调用 chatWorkbuddy。")
|
|
447
|
-
return 0
|
|
448
|
-
|
|
449
|
-
payload_data = {"query": query}
|
|
450
|
-
user_id = _resolve_user_id(args)
|
|
451
|
-
wants_opt_out = _is_opt_out_query(query)
|
|
452
|
-
wants_unbind = _is_unbind_query(query)
|
|
453
|
-
if wants_opt_out:
|
|
454
|
-
user_id = _generate_user_id()
|
|
455
|
-
_save_binding(args.binding_file, user_id, BINDING_STATUS_OPTED_OUT)
|
|
456
|
-
if user_id is not None:
|
|
457
|
-
payload_data["userid"] = user_id
|
|
458
|
-
request = _build_request(args.url, payload_data)
|
|
459
|
-
|
|
460
|
-
def persist_unbound_state() -> None:
|
|
461
|
-
if wants_unbind and user_id is not None:
|
|
462
|
-
_mark_opt_out_silently(args.url, user_id, args.timeout)
|
|
463
|
-
new_user_id = _generate_user_id()
|
|
464
|
-
_mark_opt_out_silently(args.url, new_user_id, args.timeout)
|
|
465
|
-
_save_binding(args.binding_file, new_user_id, BINDING_STATUS_OPTED_OUT)
|
|
466
|
-
|
|
467
|
-
try:
|
|
468
|
-
with urllib.request.urlopen(request, timeout=args.timeout) as response:
|
|
469
|
-
content_type = response.headers.get("Content-Type", "")
|
|
470
|
-
if "text/event-stream" in content_type.lower():
|
|
471
|
-
_stream_sse_response(response)
|
|
472
|
-
persist_unbound_state()
|
|
473
|
-
return 0
|
|
474
|
-
|
|
475
|
-
body = response.read().decode("utf-8", errors="replace")
|
|
476
|
-
output = _format_response_body(body)
|
|
477
|
-
print(output, end="" if output.endswith("\n") else "\n")
|
|
478
|
-
persist_unbound_state()
|
|
479
|
-
return 0
|
|
480
|
-
except urllib.error.HTTPError as exc:
|
|
481
|
-
body = exc.read().decode("utf-8", errors="replace")
|
|
482
|
-
print(f"med-agent-proxy http error: status={exc.code}", file=sys.stderr)
|
|
483
|
-
if body:
|
|
484
|
-
print(body, file=sys.stderr)
|
|
485
|
-
return 1
|
|
486
|
-
except urllib.error.URLError as exc:
|
|
487
|
-
print(f"med-agent-proxy network error: {exc.reason}", file=sys.stderr)
|
|
488
|
-
return 1
|
|
489
|
-
except TimeoutError:
|
|
490
|
-
print("med-agent-proxy timeout error", file=sys.stderr)
|
|
491
|
-
return 1
|
|
492
|
-
except Exception as exc: # Keep the skill deterministic and transparent for unexpected runtime failures.
|
|
493
|
-
print(f"med-agent-proxy unexpected error: {exc}", file=sys.stderr)
|
|
494
|
-
return 1
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
if __name__ == "__main__":
|
|
498
|
-
raise SystemExit(main())
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "career-broker",
|
|
3
|
-
"version": "0.3.0",
|
|
4
|
-
"description": "Your dedicated career broker at Tencent — understands your work, helps you access internal resources, and walks the next move with you.",
|
|
5
|
-
"author": {
|
|
6
|
-
"name": "Career Broker",
|
|
7
|
-
"email": "career-broker@tencent.com"
|
|
8
|
-
},
|
|
9
|
-
"expertType": "agent",
|
|
10
|
-
"agentName": "career-broker",
|
|
11
|
-
"agents": [
|
|
12
|
-
"./agents/career-broker.md"
|
|
13
|
-
],
|
|
14
|
-
"skills": [
|
|
15
|
-
"./skills/career-broker-core",
|
|
16
|
-
"./skills/profile-perception",
|
|
17
|
-
"./skills/career-qa",
|
|
18
|
-
"./skills/ai-career-agent",
|
|
19
|
-
"./skills/career-development-consultant",
|
|
20
|
-
"./skills/mentor-recommender",
|
|
21
|
-
"./skills/liveflow-job-recommender",
|
|
22
|
-
"./skills/resume-generator"
|
|
23
|
-
],
|
|
24
|
-
"displayName": {
|
|
25
|
-
"en": "Tencent Career Broker",
|
|
26
|
-
"zh": "鹅厂职业经纪人"
|
|
27
|
-
},
|
|
28
|
-
"profession": {
|
|
29
|
-
"en": "Your Career Broker",
|
|
30
|
-
"zh": "鹅厂职业经纪人"
|
|
31
|
-
},
|
|
32
|
-
"displayDescription": {
|
|
33
|
-
"en": "I help you clarify your career profile, discuss growth and transition directions, and recommend courses, experience articles, internal cases, and liveflow opportunities.",
|
|
34
|
-
"zh": "陪你梳理职业画像,讨论发展与转型方向,并推荐课程、经验文章、内部案例和活水机会。"
|
|
35
|
-
},
|
|
36
|
-
"avatar": "avatars/expert.png",
|
|
37
|
-
"categoryId": "09-OperationsHR",
|
|
38
|
-
"defaultInitPrompt": {
|
|
39
|
-
"en": "As my career broker, what can you do for me?",
|
|
40
|
-
"zh": "作为我的经纪人,你可以做什么事情?"
|
|
41
|
-
},
|
|
42
|
-
"tags": [
|
|
43
|
-
{
|
|
44
|
-
"en": "Career Growth",
|
|
45
|
-
"zh": "职业成长"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"en": "Resource Connection",
|
|
49
|
-
"zh": "资源链接"
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
"en": "Internal Opportunities",
|
|
53
|
-
"zh": "内部机会"
|
|
54
|
-
}
|
|
55
|
-
],
|
|
56
|
-
"quickPrompts": [
|
|
57
|
-
{
|
|
58
|
-
"en": "As my career broker, what can you do for me?",
|
|
59
|
-
"zh": "作为我的经纪人,你可以做什么事情?"
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
"en": "Recommend internal resources based on my situation",
|
|
63
|
-
"zh": "根据我的情况推荐司内资源"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"en": "Quick check — am I even eligible for liveflow right now?",
|
|
67
|
-
"zh": "我现在到底能不能走活水?帮我看看资格"
|
|
68
|
-
}
|
|
69
|
-
],
|
|
70
|
-
"plugin": "career-broker",
|
|
71
|
-
"userConfig": {
|
|
72
|
-
"TAIHU_TOKEN": {
|
|
73
|
-
"type": "string",
|
|
74
|
-
"label": "太湖 PAT(集团统一鉴权 · 可选)",
|
|
75
|
-
"description": "招活MCP(recruit-mcp)现已支持在 WorkBuddy 直接弹窗连接授权(点「连接」用太湖 SSO 授权即可,无需在此手填)。仅当你的客户端不支持弹窗连接、需手动配置时,才在此填太湖 PAT:https://tai.it.woa.com/user/pat 创建 Personal Access Token,粘贴进来(不要带 Bearer 前缀)。",
|
|
76
|
-
"required": false,
|
|
77
|
-
"sensitive": true
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
"dependencies": {
|
|
81
|
-
"mcpServers": {
|
|
82
|
-
"recruit-mcp": {
|
|
83
|
-
"type": "http",
|
|
84
|
-
"url": "https://zhaopin.mcp.it.woa.com",
|
|
85
|
-
"headers": {
|
|
86
|
-
"Authorization": "Bearer ${user_config.TAIHU_TOKEN}"
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
"自评MCP": {
|
|
90
|
-
"type": "http",
|
|
91
|
-
"url": "https://self-assess.mcp.it.woa.com"
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2026-09-29T03:25:12.972028+00:00
|