dsh-plugin-t-expert 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/LICENSE +21 -0
- package/README.md +215 -0
- package/THIRD-PARTY-NOTICES +33 -0
- package/cordis.patch.yml +7 -0
- package/data/experts/academic/academic-anthropologist.md +125 -0
- package/data/experts/academic/academic-geographer.md +127 -0
- package/data/experts/academic/academic-historian.md +123 -0
- package/data/experts/academic/academic-narratologist.md +118 -0
- package/data/experts/academic/academic-psychologist.md +118 -0
- package/data/experts/academic/academic-statistician.md +144 -0
- package/data/experts/design/design-brand-guardian.md +322 -0
- package/data/experts/design/design-image-prompt-engineer.md +236 -0
- package/data/experts/design/design-inclusive-visuals-specialist.md +71 -0
- package/data/experts/design/design-persona-walkthrough.md +272 -0
- package/data/experts/design/design-ui-designer.md +383 -0
- package/data/experts/design/design-ui-finish-gate-reviewer.md +217 -0
- package/data/experts/design/design-ux-architect.md +469 -0
- package/data/experts/design/design-ux-researcher.md +329 -0
- package/data/experts/design/design-visual-storyteller.md +149 -0
- package/data/experts/design/design-whimsy-injector.md +438 -0
- package/data/experts/engineering/engineering-ai-data-remediation-engineer.md +211 -0
- package/data/experts/engineering/engineering-ai-engineer.md +146 -0
- package/data/experts/engineering/engineering-api-platform-engineer.md +162 -0
- package/data/experts/engineering/engineering-ats-validator-architect.md +383 -0
- package/data/experts/engineering/engineering-autonomous-optimization-architect.md +107 -0
- package/data/experts/engineering/engineering-backend-architect.md +236 -0
- package/data/experts/engineering/engineering-china-network-engineer.md +252 -0
- package/data/experts/engineering/engineering-cms-developer.md +536 -0
- package/data/experts/engineering/engineering-code-reviewer.md +76 -0
- package/data/experts/engineering/engineering-codebase-onboarding-engineer.md +173 -0
- package/data/experts/engineering/engineering-data-engineer.md +306 -0
- package/data/experts/engineering/engineering-data-visualization-engineer.md +151 -0
- package/data/experts/engineering/engineering-database-optimizer.md +176 -0
- package/data/experts/engineering/engineering-database-reliability-engineer.md +162 -0
- package/data/experts/engineering/engineering-desktop-app-engineer.md +204 -0
- package/data/experts/engineering/engineering-developer-tooling-engineer.md +153 -0
- package/data/experts/engineering/engineering-devops-automator.md +376 -0
- package/data/experts/engineering/engineering-drupal-performance.md +347 -0
- package/data/experts/engineering/engineering-drupal-shopping-cart.md +360 -0
- package/data/experts/engineering/engineering-email-intelligence-engineer.md +353 -0
- package/data/experts/engineering/engineering-embedded-firmware-engineer.md +173 -0
- package/data/experts/engineering/engineering-feishu-integration-developer.md +598 -0
- package/data/experts/engineering/engineering-filament-optimization-specialist.md +283 -0
- package/data/experts/engineering/engineering-finops-engineer.md +153 -0
- package/data/experts/engineering/engineering-frontend-developer.md +225 -0
- package/data/experts/engineering/engineering-gaussdb-expert.md +334 -0
- package/data/experts/engineering/engineering-git-workflow-master.md +84 -0
- package/data/experts/engineering/engineering-i18n-engineer.md +184 -0
- package/data/experts/engineering/engineering-identity-access-engineer.md +196 -0
- package/data/experts/engineering/engineering-incident-response-commander.md +444 -0
- package/data/experts/engineering/engineering-iot-fleet-engineer.md +148 -0
- package/data/experts/engineering/engineering-it-service-manager.md +561 -0
- package/data/experts/engineering/engineering-knowledge-graph-engineer.md +368 -0
- package/data/experts/engineering/engineering-llm-post-training-engineer.md +166 -0
- package/data/experts/engineering/engineering-minimal-change-engineer.md +207 -0
- package/data/experts/engineering/engineering-mobile-app-builder.md +493 -0
- package/data/experts/engineering/engineering-mobile-release-engineer.md +163 -0
- package/data/experts/engineering/engineering-multi-agent-systems-architect.md +600 -0
- package/data/experts/engineering/engineering-network-engineer.md +239 -0
- package/data/experts/engineering/engineering-orgscript-engineer.md +113 -0
- package/data/experts/engineering/engineering-payments-billing-engineer.md +194 -0
- package/data/experts/engineering/engineering-pdf-engine-architect.md +666 -0
- package/data/experts/engineering/engineering-platform-engineer.md +270 -0
- package/data/experts/engineering/engineering-privacy-engineer.md +152 -0
- package/data/experts/engineering/engineering-prompt-engineer.md +202 -0
- package/data/experts/engineering/engineering-rag-pipeline-engineer.md +437 -0
- package/data/experts/engineering/engineering-rapid-prototyper.md +462 -0
- package/data/experts/engineering/engineering-realtime-collaboration-engineer.md +187 -0
- package/data/experts/engineering/engineering-rust-refactoring-specialist.md +313 -0
- package/data/experts/engineering/engineering-search-relevance-engineer.md +237 -0
- package/data/experts/engineering/engineering-section-508-specialist.md +339 -0
- package/data/experts/engineering/engineering-senior-developer.md +176 -0
- package/data/experts/engineering/engineering-software-architect.md +112 -0
- package/data/experts/engineering/engineering-solidity-smart-contract-engineer.md +522 -0
- package/data/experts/engineering/engineering-sre.md +90 -0
- package/data/experts/engineering/engineering-technical-writer.md +393 -0
- package/data/experts/engineering/engineering-universal-document-compiler.md +344 -0
- package/data/experts/engineering/engineering-uswds-developer.md +340 -0
- package/data/experts/engineering/engineering-video-streaming-engineer.md +150 -0
- package/data/experts/engineering/engineering-voice-ai-integration-engineer.md +561 -0
- package/data/experts/engineering/engineering-webassembly-engineer.md +156 -0
- package/data/experts/engineering/engineering-wechat-mini-program-developer.md +350 -0
- package/data/experts/engineering/engineering-wordpress-performance.md +346 -0
- package/data/experts/engineering/engineering-wordpress-shopping-cart.md +346 -0
- package/data/experts/finance/finance-bookkeeper-controller.md +260 -0
- package/data/experts/finance/finance-financial-analyst.md +234 -0
- package/data/experts/finance/finance-fpa-analyst.md +263 -0
- package/data/experts/finance/finance-investment-researcher.md +272 -0
- package/data/experts/finance/finance-tax-strategist.md +239 -0
- package/data/experts/game-development/blender/blender-addon-engineer.md +234 -0
- package/data/experts/game-development/economy-designer.md +156 -0
- package/data/experts/game-development/game-audio-engineer.md +264 -0
- package/data/experts/game-development/game-designer.md +167 -0
- package/data/experts/game-development/godot/godot-gameplay-scripter.md +334 -0
- package/data/experts/game-development/godot/godot-multiplayer-engineer.md +297 -0
- package/data/experts/game-development/godot/godot-shader-developer.md +266 -0
- package/data/experts/game-development/level-designer.md +208 -0
- package/data/experts/game-development/narrative-designer.md +243 -0
- package/data/experts/game-development/roblox-studio/roblox-avatar-creator.md +297 -0
- package/data/experts/game-development/roblox-studio/roblox-experience-designer.md +305 -0
- package/data/experts/game-development/roblox-studio/roblox-systems-scripter.md +325 -0
- package/data/experts/game-development/technical-artist.md +229 -0
- package/data/experts/game-development/unity/unity-architect.md +271 -0
- package/data/experts/game-development/unity/unity-editor-tool-developer.md +310 -0
- package/data/experts/game-development/unity/unity-multiplayer-engineer.md +321 -0
- package/data/experts/game-development/unity/unity-shader-graph-artist.md +269 -0
- package/data/experts/game-development/unreal-engine/unreal-multiplayer-architect.md +313 -0
- package/data/experts/game-development/unreal-engine/unreal-systems-engineer.md +310 -0
- package/data/experts/game-development/unreal-engine/unreal-technical-artist.md +256 -0
- package/data/experts/game-development/unreal-engine/unreal-world-builder.md +273 -0
- package/data/experts/gis/gis-3d-scene-developer.md +111 -0
- package/data/experts/gis/gis-analyst.md +91 -0
- package/data/experts/gis/gis-bim-specialist.md +108 -0
- package/data/experts/gis/gis-cartography-designer.md +150 -0
- package/data/experts/gis/gis-drone-reality-mapping.md +120 -0
- package/data/experts/gis/gis-geoai-ml-engineer.md +105 -0
- package/data/experts/gis/gis-geoprocessing-specialist.md +97 -0
- package/data/experts/gis/gis-qa-engineer.md +133 -0
- package/data/experts/gis/gis-solution-engineer.md +101 -0
- package/data/experts/gis/gis-spatial-data-engineer.md +97 -0
- package/data/experts/gis/gis-spatial-data-scientist.md +111 -0
- package/data/experts/gis/gis-technical-consultant.md +86 -0
- package/data/experts/gis/gis-web-gis-developer.md +108 -0
- package/data/experts/healthcare/healthcare-clinical-evidence-agent.md +231 -0
- package/data/experts/healthcare/healthcare-innovation-strategist.md +433 -0
- package/data/experts/healthcare/healthcare-sovereign-health-systems-agent.md +312 -0
- package/data/experts/marketing/marketing-aeo-foundations.md +264 -0
- package/data/experts/marketing/marketing-agentic-search-optimizer.md +313 -0
- package/data/experts/marketing/marketing-ai-citation-strategist.md +172 -0
- package/data/experts/marketing/marketing-app-store-optimizer.md +321 -0
- package/data/experts/marketing/marketing-baidu-seo-specialist.md +226 -0
- package/data/experts/marketing/marketing-bilibili-content-strategist.md +199 -0
- package/data/experts/marketing/marketing-book-co-author.md +110 -0
- package/data/experts/marketing/marketing-carousel-growth-engine.md +199 -0
- package/data/experts/marketing/marketing-china-ecommerce-operator.md +283 -0
- package/data/experts/marketing/marketing-china-market-localization-strategist.md +283 -0
- package/data/experts/marketing/marketing-content-creator.md +54 -0
- package/data/experts/marketing/marketing-cross-border-ecommerce.md +259 -0
- package/data/experts/marketing/marketing-douyin-strategist.md +149 -0
- package/data/experts/marketing/marketing-email-strategist.md +249 -0
- package/data/experts/marketing/marketing-global-podcast-strategist.md +206 -0
- package/data/experts/marketing/marketing-growth-hacker.md +54 -0
- package/data/experts/marketing/marketing-instagram-curator.md +113 -0
- package/data/experts/marketing/marketing-kuaishou-strategist.md +223 -0
- package/data/experts/marketing/marketing-linkedin-content-creator.md +214 -0
- package/data/experts/marketing/marketing-livestream-commerce-coach.md +305 -0
- package/data/experts/marketing/marketing-multi-platform-publisher.md +217 -0
- package/data/experts/marketing/marketing-podcast-strategist.md +277 -0
- package/data/experts/marketing/marketing-pr-communications-manager.md +473 -0
- package/data/experts/marketing/marketing-private-domain-operator.md +308 -0
- package/data/experts/marketing/marketing-reddit-community-builder.md +123 -0
- package/data/experts/marketing/marketing-seo-specialist.md +370 -0
- package/data/experts/marketing/marketing-short-video-editing-coach.md +412 -0
- package/data/experts/marketing/marketing-social-media-strategist.md +125 -0
- package/data/experts/marketing/marketing-tiktok-strategist.md +125 -0
- package/data/experts/marketing/marketing-twitter-engager.md +126 -0
- package/data/experts/marketing/marketing-video-optimization-specialist.md +119 -0
- package/data/experts/marketing/marketing-wechat-official-account.md +145 -0
- package/data/experts/marketing/marketing-weibo-strategist.md +240 -0
- package/data/experts/marketing/marketing-x-twitter-intelligence-analyst.md +161 -0
- package/data/experts/marketing/marketing-xiaohongshu-specialist.md +138 -0
- package/data/experts/marketing/marketing-zhihu-strategist.md +162 -0
- package/data/experts/paid-media/paid-media-auditor.md +71 -0
- package/data/experts/paid-media/paid-media-creative-strategist.md +71 -0
- package/data/experts/paid-media/paid-media-paid-social-strategist.md +71 -0
- package/data/experts/paid-media/paid-media-ppc-strategist.md +71 -0
- package/data/experts/paid-media/paid-media-programmatic-buyer.md +71 -0
- package/data/experts/paid-media/paid-media-search-query-analyst.md +71 -0
- package/data/experts/paid-media/paid-media-tracking-specialist.md +71 -0
- package/data/experts/product/product-behavioral-nudge-engine.md +80 -0
- package/data/experts/product/product-feedback-synthesizer.md +119 -0
- package/data/experts/product/product-manager.md +469 -0
- package/data/experts/product/product-sprint-prioritizer.md +154 -0
- package/data/experts/product/product-trend-researcher.md +159 -0
- package/data/experts/project-management/project-management-experiment-tracker.md +198 -0
- package/data/experts/project-management/project-management-jira-workflow-steward.md +230 -0
- package/data/experts/project-management/project-management-meeting-notes-specialist.md +95 -0
- package/data/experts/project-management/project-management-project-shepherd.md +194 -0
- package/data/experts/project-management/project-management-studio-operations.md +200 -0
- package/data/experts/project-management/project-management-studio-producer.md +203 -0
- package/data/experts/project-management/project-manager-senior.md +135 -0
- package/data/experts/research/research-synthesist.md +136 -0
- package/data/experts/sales/sales-account-strategist.md +227 -0
- package/data/experts/sales/sales-coach.md +271 -0
- package/data/experts/sales/sales-deal-strategist.md +180 -0
- package/data/experts/sales/sales-discovery-coach.md +225 -0
- package/data/experts/sales/sales-engineer.md +182 -0
- package/data/experts/sales/sales-offer-lead-gen-strategist.md +257 -0
- package/data/experts/sales/sales-outbound-strategist.md +201 -0
- package/data/experts/sales/sales-pipeline-analyst.md +267 -0
- package/data/experts/sales/sales-proposal-strategist.md +217 -0
- package/data/experts/security/security-ai-generated-code-auditor.md +207 -0
- package/data/experts/security/security-appsec-engineer.md +491 -0
- package/data/experts/security/security-architect.md +304 -0
- package/data/experts/security/security-blockchain-security-auditor.md +463 -0
- package/data/experts/security/security-cloud-security-architect.md +523 -0
- package/data/experts/security/security-compliance-auditor.md +158 -0
- package/data/experts/security/security-incident-responder.md +437 -0
- package/data/experts/security/security-penetration-tester.md +399 -0
- package/data/experts/security/security-secrets-credential-engineer.md +176 -0
- package/data/experts/security/security-senior-secops.md +750 -0
- package/data/experts/security/security-threat-detection-engineer.md +534 -0
- package/data/experts/security/security-threat-intelligence-analyst.md +644 -0
- package/data/experts/spatial-computing/macos-spatial-metal-engineer.md +337 -0
- package/data/experts/spatial-computing/terminal-integration-specialist.md +70 -0
- package/data/experts/spatial-computing/visionos-spatial-engineer.md +54 -0
- package/data/experts/spatial-computing/xr-cockpit-interaction-specialist.md +32 -0
- package/data/experts/spatial-computing/xr-immersive-developer.md +32 -0
- package/data/experts/spatial-computing/xr-interface-architect.md +32 -0
- package/data/experts/specialized/accounts-payable-agent.md +185 -0
- package/data/experts/specialized/agentic-identity-trust.md +387 -0
- package/data/experts/specialized/agents-orchestrator.md +367 -0
- package/data/experts/specialized/automation-governance-architect.md +216 -0
- package/data/experts/specialized/business-strategist.md +488 -0
- package/data/experts/specialized/change-management-consultant.md +497 -0
- package/data/experts/specialized/chief-financial-officer.md +388 -0
- package/data/experts/specialized/corporate-training-designer.md +192 -0
- package/data/experts/specialized/customer-service.md +398 -0
- package/data/experts/specialized/customer-success-manager.md +460 -0
- package/data/experts/specialized/data-consolidation-agent.md +60 -0
- package/data/experts/specialized/data-privacy-officer.md +412 -0
- package/data/experts/specialized/esg-sustainability-officer.md +396 -0
- package/data/experts/specialized/government-digital-presales-consultant.md +363 -0
- package/data/experts/specialized/grant-writer.md +511 -0
- package/data/experts/specialized/healthcare-aging-parent-care-companion.md +414 -0
- package/data/experts/specialized/healthcare-customer-service.md +389 -0
- package/data/experts/specialized/healthcare-marketing-compliance.md +395 -0
- package/data/experts/specialized/hospitality-guest-services.md +603 -0
- package/data/experts/specialized/hr-onboarding.md +451 -0
- package/data/experts/specialized/identity-graph-operator.md +260 -0
- package/data/experts/specialized/language-translator.md +264 -0
- package/data/experts/specialized/legal-billing-time-tracking.md +569 -0
- package/data/experts/specialized/legal-client-intake.md +492 -0
- package/data/experts/specialized/legal-document-review.md +454 -0
- package/data/experts/specialized/loan-officer-assistant.md +555 -0
- package/data/experts/specialized/lsp-index-engineer.md +314 -0
- package/data/experts/specialized/ma-integration-manager.md +427 -0
- package/data/experts/specialized/medical-billing-coding-specialist.md +491 -0
- package/data/experts/specialized/operations-manager.md +399 -0
- package/data/experts/specialized/organizational-psychologist.md +391 -0
- package/data/experts/specialized/personal-growth-mentor.md +159 -0
- package/data/experts/specialized/real-estate-buyer-seller.md +596 -0
- package/data/experts/specialized/recruitment-specialist.md +509 -0
- package/data/experts/specialized/report-distribution-agent.md +65 -0
- package/data/experts/specialized/resume-tailor.md +230 -0
- package/data/experts/specialized/retail-customer-returns.md +566 -0
- package/data/experts/specialized/sales-data-extraction-agent.md +67 -0
- package/data/experts/specialized/sales-outreach.md +425 -0
- package/data/experts/specialized/specialized-chief-of-staff.md +279 -0
- package/data/experts/specialized/specialized-civil-engineer.md +356 -0
- package/data/experts/specialized/specialized-codebase-archaeologist.md +341 -0
- package/data/experts/specialized/specialized-cultural-intelligence-strategist.md +88 -0
- package/data/experts/specialized/specialized-developer-advocate.md +317 -0
- package/data/experts/specialized/specialized-document-generator.md +55 -0
- package/data/experts/specialized/specialized-fedramp-rmf-compliance.md +378 -0
- package/data/experts/specialized/specialized-focus-music-architect.md +172 -0
- package/data/experts/specialized/specialized-french-consulting-market.md +194 -0
- package/data/experts/specialized/specialized-korean-business-navigator.md +216 -0
- package/data/experts/specialized/specialized-master-plan-architect.md +157 -0
- package/data/experts/specialized/specialized-mcp-builder.md +248 -0
- package/data/experts/specialized/specialized-model-qa.md +488 -0
- package/data/experts/specialized/specialized-pricing-analyst.md +243 -0
- package/data/experts/specialized/specialized-salesforce-architect.md +182 -0
- package/data/experts/specialized/specialized-strategy-duel-agent.md +130 -0
- package/data/experts/specialized/specialized-workflow-architect.md +597 -0
- package/data/experts/specialized/study-abroad-advisor.md +282 -0
- package/data/experts/specialized/supply-chain-strategist.md +582 -0
- package/data/experts/specialized/zk-steward.md +211 -0
- package/data/experts/support/support-analytics-reporter.md +365 -0
- package/data/experts/support/support-executive-summary-generator.md +212 -0
- package/data/experts/support/support-finance-tracker.md +442 -0
- package/data/experts/support/support-infrastructure-maintainer.md +618 -0
- package/data/experts/support/support-legal-compliance-checker.md +588 -0
- package/data/experts/support/support-support-responder.md +585 -0
- package/data/experts/testing/testing-accessibility-auditor.md +316 -0
- package/data/experts/testing/testing-api-tester.md +306 -0
- package/data/experts/testing/testing-evidence-collector.md +210 -0
- package/data/experts/testing/testing-performance-benchmarker.md +268 -0
- package/data/experts/testing/testing-reality-checker.md +249 -0
- package/data/experts/testing/testing-test-automation-engineer.md +179 -0
- package/data/experts/testing/testing-test-results-analyzer.md +305 -0
- package/data/experts/testing/testing-tool-evaluator.md +394 -0
- package/data/experts/testing/testing-workflow-optimizer.md +450 -0
- package/data/source.json +27 -0
- package/data/t-team.config.json +998 -0
- package/data/team-profiles.py +365 -0
- package/data/teams.json +581 -0
- package/data/teams.resolved.json +1121 -0
- package/data/zh/COVERAGE.json +20 -0
- package/data/zh/academic/academic-anthropologist.md +124 -0
- package/data/zh/academic/academic-geographer.md +126 -0
- package/data/zh/academic/academic-historian.md +122 -0
- package/data/zh/academic/academic-narratologist.md +117 -0
- package/data/zh/academic/academic-psychologist.md +117 -0
- package/data/zh/academic/academic-statistician.md +40 -0
- package/data/zh/descriptions.json +281 -0
- package/data/zh/design/design-brand-guardian.md +321 -0
- package/data/zh/design/design-image-prompt-engineer.md +255 -0
- package/data/zh/design/design-inclusive-visuals-specialist.md +177 -0
- package/data/zh/design/design-persona-walkthrough.md +271 -0
- package/data/zh/design/design-ui-designer.md +382 -0
- package/data/zh/design/design-ui-finish-gate-reviewer.md +40 -0
- package/data/zh/design/design-ux-architect.md +482 -0
- package/data/zh/design/design-ux-researcher.md +328 -0
- package/data/zh/design/design-visual-storyteller.md +159 -0
- package/data/zh/design/design-whimsy-injector.md +453 -0
- package/data/zh/divisions.json +74 -0
- package/data/zh/engineering/engineering-ai-data-remediation-engineer.md +209 -0
- package/data/zh/engineering/engineering-ai-engineer.md +161 -0
- package/data/zh/engineering/engineering-api-platform-engineer.md +40 -0
- package/data/zh/engineering/engineering-ats-validator-architect.md +383 -0
- package/data/zh/engineering/engineering-autonomous-optimization-architect.md +115 -0
- package/data/zh/engineering/engineering-backend-architect.md +234 -0
- package/data/zh/engineering/engineering-china-network-engineer.md +252 -0
- package/data/zh/engineering/engineering-cms-developer.md +534 -0
- package/data/zh/engineering/engineering-code-reviewer.md +172 -0
- package/data/zh/engineering/engineering-codebase-onboarding-engineer.md +172 -0
- package/data/zh/engineering/engineering-data-engineer.md +324 -0
- package/data/zh/engineering/engineering-data-visualization-engineer.md +40 -0
- package/data/zh/engineering/engineering-database-optimizer.md +175 -0
- package/data/zh/engineering/engineering-database-reliability-engineer.md +40 -0
- package/data/zh/engineering/engineering-desktop-app-engineer.md +40 -0
- package/data/zh/engineering/engineering-developer-tooling-engineer.md +40 -0
- package/data/zh/engineering/engineering-devops-automator.md +375 -0
- package/data/zh/engineering/engineering-drupal-performance.md +40 -0
- package/data/zh/engineering/engineering-drupal-shopping-cart.md +359 -0
- package/data/zh/engineering/engineering-email-intelligence-engineer.md +349 -0
- package/data/zh/engineering/engineering-embedded-firmware-engineer.md +168 -0
- package/data/zh/engineering/engineering-feishu-integration-developer.md +597 -0
- package/data/zh/engineering/engineering-filament-optimization-specialist.md +283 -0
- package/data/zh/engineering/engineering-finops-engineer.md +40 -0
- package/data/zh/engineering/engineering-frontend-developer.md +224 -0
- package/data/zh/engineering/engineering-gaussdb-expert.md +40 -0
- package/data/zh/engineering/engineering-git-workflow-master.md +220 -0
- package/data/zh/engineering/engineering-i18n-engineer.md +40 -0
- package/data/zh/engineering/engineering-identity-access-engineer.md +40 -0
- package/data/zh/engineering/engineering-incident-response-commander.md +465 -0
- package/data/zh/engineering/engineering-iot-fleet-engineer.md +40 -0
- package/data/zh/engineering/engineering-it-service-manager.md +560 -0
- package/data/zh/engineering/engineering-knowledge-graph-engineer.md +40 -0
- package/data/zh/engineering/engineering-llm-post-training-engineer.md +40 -0
- package/data/zh/engineering/engineering-minimal-change-engineer.md +206 -0
- package/data/zh/engineering/engineering-mobile-app-builder.md +434 -0
- package/data/zh/engineering/engineering-mobile-release-engineer.md +40 -0
- package/data/zh/engineering/engineering-multi-agent-systems-architect.md +599 -0
- package/data/zh/engineering/engineering-network-engineer.md +40 -0
- package/data/zh/engineering/engineering-orgscript-engineer.md +112 -0
- package/data/zh/engineering/engineering-payments-billing-engineer.md +40 -0
- package/data/zh/engineering/engineering-pdf-engine-architect.md +666 -0
- package/data/zh/engineering/engineering-platform-engineer.md +271 -0
- package/data/zh/engineering/engineering-privacy-engineer.md +40 -0
- package/data/zh/engineering/engineering-prompt-engineer.md +203 -0
- package/data/zh/engineering/engineering-rag-pipeline-engineer.md +40 -0
- package/data/zh/engineering/engineering-rapid-prototyper.md +461 -0
- package/data/zh/engineering/engineering-realtime-collaboration-engineer.md +40 -0
- package/data/zh/engineering/engineering-rust-refactoring-specialist.md +40 -0
- package/data/zh/engineering/engineering-search-relevance-engineer.md +40 -0
- package/data/zh/engineering/engineering-section-508-specialist.md +40 -0
- package/data/zh/engineering/engineering-senior-developer.md +177 -0
- package/data/zh/engineering/engineering-software-architect.md +200 -0
- package/data/zh/engineering/engineering-solidity-smart-contract-engineer.md +541 -0
- package/data/zh/engineering/engineering-sre.md +233 -0
- package/data/zh/engineering/engineering-technical-writer.md +409 -0
- package/data/zh/engineering/engineering-universal-document-compiler.md +344 -0
- package/data/zh/engineering/engineering-uswds-developer.md +40 -0
- package/data/zh/engineering/engineering-video-streaming-engineer.md +40 -0
- package/data/zh/engineering/engineering-voice-ai-integration-engineer.md +560 -0
- package/data/zh/engineering/engineering-webassembly-engineer.md +40 -0
- package/data/zh/engineering/engineering-wechat-mini-program-developer.md +288 -0
- package/data/zh/engineering/engineering-wordpress-performance.md +40 -0
- package/data/zh/engineering/engineering-wordpress-shopping-cart.md +345 -0
- package/data/zh/finance/finance-bookkeeper-controller.md +271 -0
- package/data/zh/finance/finance-financial-analyst.md +244 -0
- package/data/zh/finance/finance-fpa-analyst.md +272 -0
- package/data/zh/finance/finance-investment-researcher.md +283 -0
- package/data/zh/finance/finance-tax-strategist.md +250 -0
- package/data/zh/game-development/blender/blender-addon-engineer.md +233 -0
- package/data/zh/game-development/economy-designer.md +40 -0
- package/data/zh/game-development/game-audio-engineer.md +265 -0
- package/data/zh/game-development/game-designer.md +168 -0
- package/data/zh/game-development/godot/godot-gameplay-scripter.md +335 -0
- package/data/zh/game-development/godot/godot-multiplayer-engineer.md +296 -0
- package/data/zh/game-development/godot/godot-shader-developer.md +267 -0
- package/data/zh/game-development/level-designer.md +209 -0
- package/data/zh/game-development/narrative-designer.md +244 -0
- package/data/zh/game-development/roblox-studio/roblox-avatar-creator.md +298 -0
- package/data/zh/game-development/roblox-studio/roblox-experience-designer.md +306 -0
- package/data/zh/game-development/roblox-studio/roblox-systems-scripter.md +325 -0
- package/data/zh/game-development/technical-artist.md +230 -0
- package/data/zh/game-development/unity/unity-architect.md +272 -0
- package/data/zh/game-development/unity/unity-editor-tool-developer.md +300 -0
- package/data/zh/game-development/unity/unity-multiplayer-engineer.md +238 -0
- package/data/zh/game-development/unity/unity-shader-graph-artist.md +270 -0
- package/data/zh/game-development/unreal-engine/unreal-multiplayer-architect.md +314 -0
- package/data/zh/game-development/unreal-engine/unreal-systems-engineer.md +311 -0
- package/data/zh/game-development/unreal-engine/unreal-technical-artist.md +256 -0
- package/data/zh/game-development/unreal-engine/unreal-world-builder.md +274 -0
- package/data/zh/gis/gis-3d-scene-developer.md +110 -0
- package/data/zh/gis/gis-analyst.md +90 -0
- package/data/zh/gis/gis-bim-specialist.md +107 -0
- package/data/zh/gis/gis-cartography-designer.md +149 -0
- package/data/zh/gis/gis-drone-reality-mapping.md +119 -0
- package/data/zh/gis/gis-geoai-ml-engineer.md +104 -0
- package/data/zh/gis/gis-geoprocessing-specialist.md +96 -0
- package/data/zh/gis/gis-qa-engineer.md +132 -0
- package/data/zh/gis/gis-solution-engineer.md +100 -0
- package/data/zh/gis/gis-spatial-data-engineer.md +96 -0
- package/data/zh/gis/gis-spatial-data-scientist.md +110 -0
- package/data/zh/gis/gis-technical-consultant.md +85 -0
- package/data/zh/gis/gis-web-gis-developer.md +107 -0
- package/data/zh/healthcare/healthcare-clinical-evidence-agent.md +40 -0
- package/data/zh/healthcare/healthcare-innovation-strategist.md +40 -0
- package/data/zh/healthcare/healthcare-sovereign-health-systems-agent.md +40 -0
- package/data/zh/manual-bodies/engineering/engineering-ats-validator-architect.md +383 -0
- package/data/zh/manual-bodies/engineering/engineering-china-network-engineer.md +252 -0
- package/data/zh/manual-bodies/engineering/engineering-pdf-engine-architect.md +666 -0
- package/data/zh/manual-bodies/engineering/engineering-platform-engineer.md +271 -0
- package/data/zh/manual-bodies/engineering/engineering-universal-document-compiler.md +344 -0
- package/data/zh/manual-bodies/specialized/specialized-focus-music-architect.md +172 -0
- package/data/zh/manual.json +22 -0
- package/data/zh/marketing/marketing-aeo-foundations.md +263 -0
- package/data/zh/marketing/marketing-agentic-search-optimizer.md +312 -0
- package/data/zh/marketing/marketing-ai-citation-strategist.md +169 -0
- package/data/zh/marketing/marketing-app-store-optimizer.md +319 -0
- package/data/zh/marketing/marketing-baidu-seo-specialist.md +220 -0
- package/data/zh/marketing/marketing-bilibili-content-strategist.md +40 -0
- package/data/zh/marketing/marketing-book-co-author.md +109 -0
- package/data/zh/marketing/marketing-carousel-growth-engine.md +215 -0
- package/data/zh/marketing/marketing-china-ecommerce-operator.md +277 -0
- package/data/zh/marketing/marketing-china-market-localization-strategist.md +282 -0
- package/data/zh/marketing/marketing-content-creator.md +145 -0
- package/data/zh/marketing/marketing-cross-border-ecommerce.md +260 -0
- package/data/zh/marketing/marketing-douyin-strategist.md +150 -0
- package/data/zh/marketing/marketing-email-strategist.md +248 -0
- package/data/zh/marketing/marketing-global-podcast-strategist.md +204 -0
- package/data/zh/marketing/marketing-growth-hacker.md +121 -0
- package/data/zh/marketing/marketing-instagram-curator.md +179 -0
- package/data/zh/marketing/marketing-kuaishou-strategist.md +182 -0
- package/data/zh/marketing/marketing-linkedin-content-creator.md +232 -0
- package/data/zh/marketing/marketing-livestream-commerce-coach.md +303 -0
- package/data/zh/marketing/marketing-multi-platform-publisher.md +216 -0
- package/data/zh/marketing/marketing-podcast-strategist.md +278 -0
- package/data/zh/marketing/marketing-pr-communications-manager.md +472 -0
- package/data/zh/marketing/marketing-private-domain-operator.md +309 -0
- package/data/zh/marketing/marketing-reddit-community-builder.md +127 -0
- package/data/zh/marketing/marketing-seo-specialist.md +298 -0
- package/data/zh/marketing/marketing-short-video-editing-coach.md +413 -0
- package/data/zh/marketing/marketing-social-media-strategist.md +118 -0
- package/data/zh/marketing/marketing-tiktok-strategist.md +124 -0
- package/data/zh/marketing/marketing-twitter-engager.md +132 -0
- package/data/zh/marketing/marketing-video-optimization-specialist.md +128 -0
- package/data/zh/marketing/marketing-wechat-official-account.md +158 -0
- package/data/zh/marketing/marketing-weibo-strategist.md +241 -0
- package/data/zh/marketing/marketing-x-twitter-intelligence-analyst.md +160 -0
- package/data/zh/marketing/marketing-xiaohongshu-specialist.md +151 -0
- package/data/zh/marketing/marketing-zhihu-strategist.md +175 -0
- package/data/zh/names.json +281 -0
- package/data/zh/paid-media/paid-media-auditor.md +170 -0
- package/data/zh/paid-media/paid-media-creative-strategist.md +173 -0
- package/data/zh/paid-media/paid-media-paid-social-strategist.md +180 -0
- package/data/zh/paid-media/paid-media-ppc-strategist.md +180 -0
- package/data/zh/paid-media/paid-media-programmatic-buyer.md +177 -0
- package/data/zh/paid-media/paid-media-search-query-analyst.md +182 -0
- package/data/zh/paid-media/paid-media-tracking-specialist.md +199 -0
- package/data/zh/product/product-behavioral-nudge-engine.md +246 -0
- package/data/zh/product/product-feedback-synthesizer.md +175 -0
- package/data/zh/product/product-manager.md +474 -0
- package/data/zh/product/product-sprint-prioritizer.md +133 -0
- package/data/zh/product/product-trend-researcher.md +143 -0
- package/data/zh/project-management/project-management-experiment-tracker.md +206 -0
- package/data/zh/project-management/project-management-jira-workflow-steward.md +249 -0
- package/data/zh/project-management/project-management-meeting-notes-specialist.md +94 -0
- package/data/zh/project-management/project-management-project-shepherd.md +202 -0
- package/data/zh/project-management/project-management-studio-operations.md +208 -0
- package/data/zh/project-management/project-management-studio-producer.md +211 -0
- package/data/zh/project-management/project-manager-senior.md +135 -0
- package/data/zh/research/research-synthesist.md +40 -0
- package/data/zh/sales/sales-account-strategist.md +243 -0
- package/data/zh/sales/sales-coach.md +291 -0
- package/data/zh/sales/sales-deal-strategist.md +204 -0
- package/data/zh/sales/sales-discovery-coach.md +230 -0
- package/data/zh/sales/sales-engineer.md +200 -0
- package/data/zh/sales/sales-offer-lead-gen-strategist.md +256 -0
- package/data/zh/sales/sales-outbound-strategist.md +208 -0
- package/data/zh/sales/sales-pipeline-analyst.md +284 -0
- package/data/zh/sales/sales-proposal-strategist.md +233 -0
- package/data/zh/security/security-ai-generated-code-auditor.md +40 -0
- package/data/zh/security/security-appsec-engineer.md +490 -0
- package/data/zh/security/security-architect.md +303 -0
- package/data/zh/security/security-blockchain-security-auditor.md +462 -0
- package/data/zh/security/security-cloud-security-architect.md +522 -0
- package/data/zh/security/security-compliance-auditor.md +157 -0
- package/data/zh/security/security-incident-responder.md +436 -0
- package/data/zh/security/security-penetration-tester.md +398 -0
- package/data/zh/security/security-secrets-credential-engineer.md +40 -0
- package/data/zh/security/security-senior-secops.md +751 -0
- package/data/zh/security/security-threat-detection-engineer.md +533 -0
- package/data/zh/security/security-threat-intelligence-analyst.md +643 -0
- package/data/zh/spatial-computing/macos-spatial-metal-engineer.md +337 -0
- package/data/zh/spatial-computing/terminal-integration-specialist.md +236 -0
- package/data/zh/spatial-computing/visionos-spatial-engineer.md +282 -0
- package/data/zh/spatial-computing/xr-cockpit-interaction-specialist.md +220 -0
- package/data/zh/spatial-computing/xr-immersive-developer.md +229 -0
- package/data/zh/spatial-computing/xr-interface-architect.md +253 -0
- package/data/zh/specialized/accounts-payable-agent.md +212 -0
- package/data/zh/specialized/agentic-identity-trust.md +388 -0
- package/data/zh/specialized/agents-orchestrator.md +366 -0
- package/data/zh/specialized/automation-governance-architect.md +215 -0
- package/data/zh/specialized/business-strategist.md +487 -0
- package/data/zh/specialized/change-management-consultant.md +495 -0
- package/data/zh/specialized/chief-financial-officer.md +390 -0
- package/data/zh/specialized/corporate-training-designer.md +191 -0
- package/data/zh/specialized/customer-service.md +40 -0
- package/data/zh/specialized/customer-success-manager.md +458 -0
- package/data/zh/specialized/data-consolidation-agent.md +327 -0
- package/data/zh/specialized/data-privacy-officer.md +411 -0
- package/data/zh/specialized/esg-sustainability-officer.md +395 -0
- package/data/zh/specialized/government-digital-presales-consultant.md +362 -0
- package/data/zh/specialized/grant-writer.md +510 -0
- package/data/zh/specialized/healthcare-aging-parent-care-companion.md +40 -0
- package/data/zh/specialized/healthcare-customer-service.md +388 -0
- package/data/zh/specialized/healthcare-marketing-compliance.md +394 -0
- package/data/zh/specialized/hospitality-guest-services.md +597 -0
- package/data/zh/specialized/hr-onboarding.md +450 -0
- package/data/zh/specialized/identity-graph-operator.md +270 -0
- package/data/zh/specialized/language-translator.md +275 -0
- package/data/zh/specialized/legal-billing-time-tracking.md +566 -0
- package/data/zh/specialized/legal-client-intake.md +487 -0
- package/data/zh/specialized/legal-document-review.md +452 -0
- package/data/zh/specialized/loan-officer-assistant.md +549 -0
- package/data/zh/specialized/lsp-index-engineer.md +334 -0
- package/data/zh/specialized/ma-integration-manager.md +426 -0
- package/data/zh/specialized/medical-billing-coding-specialist.md +489 -0
- package/data/zh/specialized/operations-manager.md +398 -0
- package/data/zh/specialized/organizational-psychologist.md +390 -0
- package/data/zh/specialized/personal-growth-mentor.md +158 -0
- package/data/zh/specialized/real-estate-buyer-seller.md +594 -0
- package/data/zh/specialized/recruitment-specialist.md +49 -0
- package/data/zh/specialized/report-distribution-agent.md +354 -0
- package/data/zh/specialized/resume-tailor.md +40 -0
- package/data/zh/specialized/retail-customer-returns.md +564 -0
- package/data/zh/specialized/sales-data-extraction-agent.md +159 -0
- package/data/zh/specialized/sales-outreach.md +40 -0
- package/data/zh/specialized/specialized-chief-of-staff.md +40 -0
- package/data/zh/specialized/specialized-civil-engineer.md +355 -0
- package/data/zh/specialized/specialized-codebase-archaeologist.md +40 -0
- package/data/zh/specialized/specialized-cultural-intelligence-strategist.md +168 -0
- package/data/zh/specialized/specialized-developer-advocate.md +334 -0
- package/data/zh/specialized/specialized-document-generator.md +346 -0
- package/data/zh/specialized/specialized-fedramp-rmf-compliance.md +40 -0
- package/data/zh/specialized/specialized-focus-music-architect.md +172 -0
- package/data/zh/specialized/specialized-french-consulting-market.md +46 -0
- package/data/zh/specialized/specialized-korean-business-navigator.md +46 -0
- package/data/zh/specialized/specialized-master-plan-architect.md +40 -0
- package/data/zh/specialized/specialized-mcp-builder.md +351 -0
- package/data/zh/specialized/specialized-model-qa.md +507 -0
- package/data/zh/specialized/specialized-pricing-analyst.md +242 -0
- package/data/zh/specialized/specialized-salesforce-architect.md +179 -0
- package/data/zh/specialized/specialized-strategy-duel-agent.md +129 -0
- package/data/zh/specialized/specialized-workflow-architect.md +596 -0
- package/data/zh/specialized/study-abroad-advisor.md +281 -0
- package/data/zh/specialized/supply-chain-strategist.md +581 -0
- package/data/zh/specialized/zk-steward.md +228 -0
- package/data/zh/support/support-analytics-reporter.md +364 -0
- package/data/zh/support/support-executive-summary-generator.md +217 -0
- package/data/zh/support/support-finance-tracker.md +447 -0
- package/data/zh/support/support-infrastructure-maintainer.md +623 -0
- package/data/zh/support/support-legal-compliance-checker.md +587 -0
- package/data/zh/support/support-support-responder.md +584 -0
- package/data/zh/testing/testing-accessibility-auditor.md +329 -0
- package/data/zh/testing/testing-api-tester.md +305 -0
- package/data/zh/testing/testing-evidence-collector.md +153 -0
- package/data/zh/testing/testing-performance-benchmarker.md +196 -0
- package/data/zh/testing/testing-reality-checker.md +235 -0
- package/data/zh/testing/testing-test-automation-engineer.md +40 -0
- package/data/zh/testing/testing-test-results-analyzer.md +313 -0
- package/data/zh/testing/testing-tool-evaluator.md +402 -0
- package/data/zh/testing/testing-workflow-optimizer.md +458 -0
- package/lib/assets/t-team/action-celebrating-v2.png +0 -0
- package/lib/assets/t-team/action-reporting-v2.png +0 -0
- package/lib/assets/t-team/action-sending-v2.png +0 -0
- package/lib/assets/t-team/action-sleeping-v2.png +0 -0
- package/lib/assets/t-team/action-thinking-v2.png +0 -0
- package/lib/assets/t-team/action-working-v2.png +0 -0
- package/lib/assets/t-team/member-data-v2.png +0 -0
- package/lib/assets/t-team/member-designer-v2.png +0 -0
- package/lib/assets/t-team/member-docs-v2.png +0 -0
- package/lib/assets/t-team/member-engineer-v2.png +0 -0
- package/lib/assets/t-team/member-operator-v2.png +0 -0
- package/lib/assets/t-team/member-qa-v2.png +0 -0
- package/lib/assets/t-team/member-researcher-v2.png +0 -0
- package/lib/assets/t-team/member-security-v2.png +0 -0
- package/lib/assets/t-team/team-lead-v2.png +0 -0
- package/lib/bootstrap.js +85 -0
- package/lib/catalog.js +376 -0
- package/lib/client.js +21034 -0
- package/lib/command.js +228 -0
- package/lib/i18n.js +136 -0
- package/lib/index.js +686 -0
- package/lib/plan-check.js +171 -0
- package/lib/remote.js +353 -0
- package/lib/squads.js +231 -0
- package/lib/teams/capabilities.js +106 -0
- package/lib/teams/command.js +143 -0
- package/lib/teams/event-types.js +12 -0
- package/lib/teams/events.js +60 -0
- package/lib/teams/harness-compat.js +179 -0
- package/lib/teams/index.js +441 -0
- package/lib/teams/members.js +602 -0
- package/lib/teams/profiles.js +572 -0
- package/lib/teams/quality-gates.js +822 -0
- package/lib/teams/scheduler.js +434 -0
- package/lib/teams/snapshot.js +181 -0
- package/lib/teams/state.js +925 -0
- package/lib/teams/tool-names.js +11 -0
- package/lib/teams/tools.js +2279 -0
- package/lib/teams/types.js +22 -0
- package/lib/teams/web-routes.js +86 -0
- package/package.json +191 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Member subagent lifecycle: spawn a continuable child per member, deliver
|
|
3
|
+
* messages into its FIFO inbox, and observe its activity.
|
|
4
|
+
*
|
|
5
|
+
* Members are durable continuable subagents of the captain, so a member keeps
|
|
6
|
+
* its conversation across turns and across harness restarts: the captain
|
|
7
|
+
* queues its next turn through {@link deliverToMember}, it works through its turn
|
|
8
|
+
* (updating team state through the `t_team_*` tools), and becomes idle
|
|
9
|
+
* again. Its final assistant message is not readable programmatically, so the
|
|
10
|
+
* member persists its report into the captain's mailbox and the task records,
|
|
11
|
+
* which the captain reads through `t_team_status`.
|
|
12
|
+
* @module t-team/members
|
|
13
|
+
*/
|
|
14
|
+
import { installModelSelection } from '@deepseek-ai/dsh-agent';
|
|
15
|
+
// Declaration merge only: makes ctx.subagents visible.
|
|
16
|
+
import { foldSubagentDescriptor } from '@deepseek-ai/dsh-subagent';
|
|
17
|
+
import { createUserMessage, LlmError, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
import { guardSubagentDelivery, installContinuableMemberSetup, queueMemberPrompt, sessionOwnEvents } from "./harness-compat.js";
|
|
20
|
+
import { acknowledgeMailbox, appendMailbox, CAPTAIN_KEY, createMessage, readRetiredMemberIds, readTeamSync, readTeam, releaseMailboxDelivery, withTeamLock, writeTeam } from "./state.js";
|
|
21
|
+
import { appendTeamEvent, captainSessionOf } from "./events.js";
|
|
22
|
+
import { TERMINAL_TASK_STATUSES } from "./types.js";
|
|
23
|
+
import { CAPTAIN_TOOL_NAMES } from "./tool-names.js";
|
|
24
|
+
/** Persona snapshot of a profile protocol; the full text lives on team.json. */
|
|
25
|
+
export const PERSONA_PROTOCOL_MAX_CHARS = 400;
|
|
26
|
+
/** Captain-only T Team tools hidden from newly spawned members. */
|
|
27
|
+
const MEMBER_DENIED_TOOLS = CAPTAIN_TOOL_NAMES;
|
|
28
|
+
/**
|
|
29
|
+
* Restore the SessionId brand on a value that round-tripped through the
|
|
30
|
+
* durable team file. The brand is erased by JSON serialization; the value
|
|
31
|
+
* originated from `startContinuable`/`agent.id`, so this cast is the boundary
|
|
32
|
+
* restoration, not a new assertion.
|
|
33
|
+
*/
|
|
34
|
+
function brandedSessionId(value) {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Validate a resolved roster against every provider catalog before any child
|
|
39
|
+
* session is created. Catalogs are advisory when empty (some adapters accept
|
|
40
|
+
* dynamic model ids), but a non-empty catalog is authoritative enough to
|
|
41
|
+
* catch a typo that would otherwise boot a child and fail on its first turn.
|
|
42
|
+
*/
|
|
43
|
+
export async function validateMemberLlmSelections(ctx, selections, signal) {
|
|
44
|
+
const catalogs = new Map();
|
|
45
|
+
for (const selection of selections) {
|
|
46
|
+
if (signal?.aborted === true)
|
|
47
|
+
throw signal.reason ?? new Error('member model validation was cancelled');
|
|
48
|
+
let catalog = catalogs.get(selection.provider);
|
|
49
|
+
if (catalog === undefined) {
|
|
50
|
+
catalog = await ctx.llm.listModels(selection.provider);
|
|
51
|
+
catalogs.set(selection.provider, catalog);
|
|
52
|
+
}
|
|
53
|
+
if (catalog.length === 0 || catalog.some((model) => model.id === selection.model))
|
|
54
|
+
continue;
|
|
55
|
+
const available = catalog.slice(0, 8).map((model) => model.id).join(', ');
|
|
56
|
+
throw new Error(`unknown member model "${selection.model}" for provider "${selection.provider}"`
|
|
57
|
+
+ `${available === '' ? '' : ` (available: ${available}${catalog.length > 8 ? ', …' : ''})`}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const MEMBER_LABEL_PREFIX = 't-team:';
|
|
61
|
+
const FALLBACK_FAILURE_CODES = new Set(['QUOTA', 'RATE_LIMIT', 'AUTH', 'MISSING_CREDENTIAL', 'NO_ADAPTER']);
|
|
62
|
+
export function isFallbackFailureCode(code) {
|
|
63
|
+
return FALLBACK_FAILURE_CODES.has(code);
|
|
64
|
+
}
|
|
65
|
+
/** Pure state transition used by the request-error handler and TDD tests. */
|
|
66
|
+
export function selectFallbackRoute(current, fallback, failureCode, alreadySwitched) {
|
|
67
|
+
if (alreadySwitched || fallback === undefined || !isFallbackFailureCode(failureCode)) {
|
|
68
|
+
return { retry: false, switched: alreadySwitched, selection: current };
|
|
69
|
+
}
|
|
70
|
+
return { retry: true, switched: true, selection: fallback };
|
|
71
|
+
}
|
|
72
|
+
/** Deliver a durable member report to the live captain at its next model step. */
|
|
73
|
+
export function steerCaptainReport(captain, from, content) {
|
|
74
|
+
try {
|
|
75
|
+
captain.steer(createUserMessage({
|
|
76
|
+
content: [{ type: 'text', text: `T Team message from member ${from}:\n\n${content}` }],
|
|
77
|
+
source: { kind: 'plugin', plugin: 't-team' },
|
|
78
|
+
}));
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Record a final turn failure, never an intermediate request retry. */
|
|
86
|
+
export async function failMemberOpenAttempt(ctx, stateRoot, teamId, memberName, failure, fallbackSession, observed) {
|
|
87
|
+
const summary = `${failure.message} (code ${failure.code})`;
|
|
88
|
+
const lockKey = `team:${stateRoot}:${teamId}`;
|
|
89
|
+
const prepared = await withTeamLock(lockKey, async () => {
|
|
90
|
+
const team = await readTeam(stateRoot, teamId);
|
|
91
|
+
if (team === undefined || team.halted === true || team.captainSessionId !== observed.captainSessionId)
|
|
92
|
+
return;
|
|
93
|
+
const member = team.members.find(candidate => candidate.name === memberName
|
|
94
|
+
&& candidate.id === observed.memberId && candidate.status !== 'removed');
|
|
95
|
+
if (member === undefined)
|
|
96
|
+
return;
|
|
97
|
+
const task = team.tasks.find(candidate => candidate.assignee === memberName
|
|
98
|
+
&& (candidate.status === 'claimed' || candidate.status === 'in_progress'));
|
|
99
|
+
// A reassign, completion, or recreated member may win the lock while the
|
|
100
|
+
// final error is queued. Only the capability observed at that event may fail.
|
|
101
|
+
if (task?.id !== observed.task?.id || task?.attemptId !== observed.task?.attemptId
|
|
102
|
+
|| task?.attempt !== observed.task?.attempt)
|
|
103
|
+
return;
|
|
104
|
+
if (task === undefined && member.status !== 'working')
|
|
105
|
+
return;
|
|
106
|
+
if (task !== undefined) {
|
|
107
|
+
task.status = 'failed';
|
|
108
|
+
task.output = summary;
|
|
109
|
+
task.updatedAt = Date.now();
|
|
110
|
+
}
|
|
111
|
+
if (ctx.agents.get(brandedSessionId(member.id))?.status !== 'running')
|
|
112
|
+
member.status = 'idle';
|
|
113
|
+
const message = {
|
|
114
|
+
...createMessage(memberName, CAPTAIN_KEY, task === undefined
|
|
115
|
+
? `Member "${memberName}" hit an unrecoverable turn failure: ${summary}. No open attempt was owned.`
|
|
116
|
+
: `Member "${memberName}" hit an unrecoverable turn failure: ${summary}. Task ${task.id} ("${task.subject}") was marked failed; reassign it or retry when ready.`),
|
|
117
|
+
deliveryClaimedAt: Date.now(),
|
|
118
|
+
};
|
|
119
|
+
await writeTeam(stateRoot, team);
|
|
120
|
+
await appendMailbox(stateRoot, team.id, CAPTAIN_KEY, message);
|
|
121
|
+
if (task !== undefined) {
|
|
122
|
+
appendTeamEvent(ctx, captainSessionOf(ctx, team.captainSessionId, fallbackSession), 't-team/task-updated', {
|
|
123
|
+
teamId, taskId: task.id, status: task.status, assignee: memberName, output: task.output,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
appendTeamEvent(ctx, captainSessionOf(ctx, team.captainSessionId, fallbackSession), 't-team/message-sent', {
|
|
127
|
+
teamId: team.id,
|
|
128
|
+
messageId: message.id,
|
|
129
|
+
from: memberName,
|
|
130
|
+
to: CAPTAIN_KEY,
|
|
131
|
+
content: message.content,
|
|
132
|
+
ts: message.ts,
|
|
133
|
+
});
|
|
134
|
+
return { captainSessionId: team.captainSessionId, message };
|
|
135
|
+
});
|
|
136
|
+
if (prepared === undefined)
|
|
137
|
+
return false;
|
|
138
|
+
// Use the same lease/acknowledgment contract as send_message, outside the
|
|
139
|
+
// team lock: steering can synchronously start another agent turn.
|
|
140
|
+
const captain = ctx.agents.get(brandedSessionId(prepared.captainSessionId));
|
|
141
|
+
const delivered = captain !== undefined && steerCaptainReport(captain, memberName, prepared.message.content);
|
|
142
|
+
await withTeamLock(lockKey, () => delivered
|
|
143
|
+
? acknowledgeMailbox(stateRoot, teamId, CAPTAIN_KEY, [prepared.message.id])
|
|
144
|
+
: releaseMailboxDelivery(stateRoot, teamId, CAPTAIN_KEY, [prepared.message.id]));
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
async function updateFallbackState(stateRoot, teamId, memberName, fallback, ctx) {
|
|
148
|
+
await withTeamLock(`team:${stateRoot}:${teamId}`, async () => {
|
|
149
|
+
const team = await readTeam(stateRoot, teamId);
|
|
150
|
+
if (team === undefined)
|
|
151
|
+
return;
|
|
152
|
+
const member = team.members.find(candidate => candidate.name === memberName);
|
|
153
|
+
if (member === undefined)
|
|
154
|
+
return;
|
|
155
|
+
member.activeProvider = fallback.provider;
|
|
156
|
+
member.activeModel = fallback.model;
|
|
157
|
+
member.fallbackActive = true;
|
|
158
|
+
await writeTeam(stateRoot, team);
|
|
159
|
+
});
|
|
160
|
+
void ctx;
|
|
161
|
+
}
|
|
162
|
+
function pendingSelectionKey(parentSessionId, label) {
|
|
163
|
+
return `${parentSessionId}\u0000${label}`;
|
|
164
|
+
}
|
|
165
|
+
function selectionFromMember(member) {
|
|
166
|
+
if (member?.provider === undefined || member.model === undefined)
|
|
167
|
+
return undefined;
|
|
168
|
+
const provider = (member.activeProvider ?? member.provider).trim();
|
|
169
|
+
const model = (member.activeModel ?? member.model).trim();
|
|
170
|
+
if (provider === '' || model === '')
|
|
171
|
+
return undefined;
|
|
172
|
+
// Effort ids belong to the original model. After a fallback, its own
|
|
173
|
+
// provider default remains authoritative, including after cold recovery.
|
|
174
|
+
const reasoningEffort = member.fallbackActive === true ? undefined : member.reasoningEffort?.trim();
|
|
175
|
+
return {
|
|
176
|
+
provider,
|
|
177
|
+
model,
|
|
178
|
+
...reasoningEffort === undefined || reasoningEffort === '' ? {} : { reasoningEffort },
|
|
179
|
+
...member.fallback === undefined || member.fallbackActive === true ? {} : { fallback: member.fallback },
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function modelSelection(selection) {
|
|
183
|
+
return {
|
|
184
|
+
provider: selection.provider,
|
|
185
|
+
model: selection.model,
|
|
186
|
+
...selection.reasoningEffort === undefined
|
|
187
|
+
? {}
|
|
188
|
+
: { reasoningEffort: ReasoningEffortId(selection.reasoningEffort) },
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Resolve one member's complete model selection. Ordinary members snapshot the
|
|
193
|
+
* captain's current request route and reasoning effort. When provider or model
|
|
194
|
+
* changes, effort is intentionally omitted so the target model materializes
|
|
195
|
+
* its own default instead of receiving an adapter-owned id from another route.
|
|
196
|
+
* An explicit effort overrides either policy; the sentinel "default" also
|
|
197
|
+
* selects the target model's default. The final effort is validated against
|
|
198
|
+
* the target model before a child is created.
|
|
199
|
+
*/
|
|
200
|
+
export async function resolveMemberLlmSelection(ctx, captain, request, signal) {
|
|
201
|
+
const explicitProvider = request.provider?.trim();
|
|
202
|
+
const explicitModel = request.model?.trim();
|
|
203
|
+
const defaultModel = request.defaultModel?.trim();
|
|
204
|
+
const explicitEffort = request.reasoningEffort?.trim();
|
|
205
|
+
const fallback = request.fallback;
|
|
206
|
+
if (request.provider !== undefined && explicitProvider === '') {
|
|
207
|
+
throw new Error('member LLM provider must not be empty');
|
|
208
|
+
}
|
|
209
|
+
if (request.model !== undefined && explicitModel === '') {
|
|
210
|
+
throw new Error('member model must not be empty');
|
|
211
|
+
}
|
|
212
|
+
if (request.defaultModel !== undefined && defaultModel === '') {
|
|
213
|
+
throw new Error('configured memberModel must not be empty');
|
|
214
|
+
}
|
|
215
|
+
if (request.reasoningEffort !== undefined && explicitEffort === '') {
|
|
216
|
+
throw new Error('member reasoning effort must not be empty');
|
|
217
|
+
}
|
|
218
|
+
if (explicitProvider !== undefined && explicitModel === undefined) {
|
|
219
|
+
throw new Error('an explicit member LLM provider requires an explicit member model');
|
|
220
|
+
}
|
|
221
|
+
const current = captain.session.requestHeader()?.config;
|
|
222
|
+
const currentProvider = current?.provider ?? captain.options.provider;
|
|
223
|
+
const currentModel = current?.model ?? captain.options.model;
|
|
224
|
+
const provider = explicitProvider ?? currentProvider;
|
|
225
|
+
const model = explicitModel ?? defaultModel ?? currentModel;
|
|
226
|
+
if (provider === undefined || model === undefined) {
|
|
227
|
+
throw new Error('cannot resolve the member LLM route from the current captain session');
|
|
228
|
+
}
|
|
229
|
+
// Effort ids belong to one exact provider/model capability. Preserve the
|
|
230
|
+
// captain's effort only on the same route; a changed route must resolve its
|
|
231
|
+
// own default. Explicit effort still wins, while "default" forces that
|
|
232
|
+
// target-default behavior even when the route did not change.
|
|
233
|
+
const sameRoute = provider === currentProvider && model === currentModel;
|
|
234
|
+
const reasoningEffort = explicitEffort === undefined
|
|
235
|
+
? sameRoute
|
|
236
|
+
? current?.reasoningEffort
|
|
237
|
+
: undefined
|
|
238
|
+
: explicitEffort === 'default'
|
|
239
|
+
? undefined
|
|
240
|
+
: ReasoningEffortId(explicitEffort);
|
|
241
|
+
const resolved = await ctx.llm.resolveCallConfig({
|
|
242
|
+
provider,
|
|
243
|
+
model,
|
|
244
|
+
...reasoningEffort === undefined
|
|
245
|
+
? {}
|
|
246
|
+
: { reasoningEffort },
|
|
247
|
+
}, signal);
|
|
248
|
+
return {
|
|
249
|
+
provider: resolved.provider,
|
|
250
|
+
model: resolved.model,
|
|
251
|
+
...resolved.reasoningEffort === undefined
|
|
252
|
+
? {}
|
|
253
|
+
: { reasoningEffort: String(resolved.reasoningEffort) },
|
|
254
|
+
...fallback === undefined ? {} : { fallback },
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Install the member selection bridge for every fresh or cold-resumed
|
|
259
|
+
* continuable child. Fresh creation reads the pending in-memory selection;
|
|
260
|
+
* cold resume restores the same selection from the owning team's durable
|
|
261
|
+
* record. Legacy members without a complete saved route retain Harness's
|
|
262
|
+
* descriptor provider/model behavior.
|
|
263
|
+
*/
|
|
264
|
+
export function installMemberSelectionRuntime(ctx, stateDir, onFailureSettled) {
|
|
265
|
+
const pending = new Map();
|
|
266
|
+
installContinuableMemberSetup(ctx, (childCtx, child) => {
|
|
267
|
+
const descriptor = foldSubagentDescriptor(sessionOwnEvents(child.session));
|
|
268
|
+
if (descriptor?.mode !== 'continuable' || !descriptor.label.startsWith(MEMBER_LABEL_PREFIX)) {
|
|
269
|
+
return () => undefined;
|
|
270
|
+
}
|
|
271
|
+
const parentSessionId = child.session.header.parentSession;
|
|
272
|
+
if (parentSessionId === undefined)
|
|
273
|
+
return () => undefined;
|
|
274
|
+
const identity = descriptor.label.slice(MEMBER_LABEL_PREFIX.length);
|
|
275
|
+
const separator = identity.indexOf(':');
|
|
276
|
+
if (separator < 1 || separator === identity.length - 1)
|
|
277
|
+
return () => undefined;
|
|
278
|
+
const teamId = identity.slice(0, separator);
|
|
279
|
+
const memberName = identity.slice(separator + 1);
|
|
280
|
+
const workspace = child.session.header.cwd ?? process.cwd();
|
|
281
|
+
const stateRoot = join(workspace, stateDir);
|
|
282
|
+
const key = pendingSelectionKey(parentSessionId, descriptor.label);
|
|
283
|
+
let selection = pending.get(key);
|
|
284
|
+
if (selection === undefined) {
|
|
285
|
+
const team = readTeamSync(stateRoot, teamId);
|
|
286
|
+
if (team?.captainSessionId !== parentSessionId)
|
|
287
|
+
return () => undefined;
|
|
288
|
+
const durableMember = team.members.find(member => member.name === memberName);
|
|
289
|
+
selection = selectionFromMember(durableMember);
|
|
290
|
+
if (selection !== undefined && (descriptor.agentProvider !== durableMember?.provider || descriptor.agentModel !== durableMember?.model)) {
|
|
291
|
+
throw new Error(`t-team: saved model route for member "${memberName}" does not match its subagent descriptor`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
let lastFailedTurn;
|
|
295
|
+
// Harness emits agent/error only after request recovery is exhausted. In
|
|
296
|
+
// particular, llm-retry's "always" policy calls downstream request-error
|
|
297
|
+
// listeners before it retries; that waterfall cannot declare a turn dead.
|
|
298
|
+
const disposeFailure = childCtx.on('agent/error', async (payload) => {
|
|
299
|
+
if (payload.agent.id !== child.id || payload.turn === lastFailedTurn)
|
|
300
|
+
return;
|
|
301
|
+
lastFailedTurn = payload.turn;
|
|
302
|
+
try {
|
|
303
|
+
// Capture the attempt synchronously at the event, before any lock wait
|
|
304
|
+
// can let a captain reassign it or replace the member/team generation.
|
|
305
|
+
const snapshot = readTeamSync(stateRoot, teamId);
|
|
306
|
+
if (snapshot?.captainSessionId !== parentSessionId)
|
|
307
|
+
return;
|
|
308
|
+
const member = snapshot.members.find(item => item.id === child.id && item.name === memberName && item.status !== 'removed');
|
|
309
|
+
if (member === undefined)
|
|
310
|
+
return;
|
|
311
|
+
const task = snapshot.tasks.find(item => item.assignee === memberName
|
|
312
|
+
&& (item.status === 'claimed' || item.status === 'in_progress'));
|
|
313
|
+
const failure = payload.error instanceof LlmError ? payload.error.failure : {
|
|
314
|
+
code: 'UNKNOWN',
|
|
315
|
+
message: payload.error instanceof Error ? payload.error.message : String(payload.error),
|
|
316
|
+
};
|
|
317
|
+
const recorded = await failMemberOpenAttempt(ctx, stateRoot, teamId, memberName, failure, child.session, {
|
|
318
|
+
captainSessionId: parentSessionId, memberId: child.id, task,
|
|
319
|
+
});
|
|
320
|
+
if (!recorded)
|
|
321
|
+
return;
|
|
322
|
+
// The final-error event precedes driver quiescence. Observe the real
|
|
323
|
+
// lifecycle and kick explicitly even if its idle event was missed.
|
|
324
|
+
// Never force an active Agent's status to idle or retry the failed task.
|
|
325
|
+
await child.whenIdle();
|
|
326
|
+
await withTeamLock(`team:${stateRoot}:${teamId}`, async () => {
|
|
327
|
+
const team = await readTeam(stateRoot, teamId);
|
|
328
|
+
const current = team?.members.find(item => item.id === child.id && item.name === memberName && item.status !== 'removed');
|
|
329
|
+
if (team?.captainSessionId !== parentSessionId || current === undefined || child.status !== 'idle')
|
|
330
|
+
return;
|
|
331
|
+
if (current.status !== 'idle') {
|
|
332
|
+
current.status = 'idle';
|
|
333
|
+
await writeTeam(stateRoot, team);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
await onFailureSettled?.(workspace, teamId, memberName);
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
ctx.logger.warn(`t-team: failed to record member turn failure: ${String(error)}`);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
// Legacy teams still need failure reporting even without a saved route.
|
|
343
|
+
if (selection === undefined)
|
|
344
|
+
return disposeFailure;
|
|
345
|
+
const selectionRef = { current: modelSelection(selection), assembled: undefined };
|
|
346
|
+
const disposeSelection = installModelSelection(childCtx, selectionRef);
|
|
347
|
+
const fallback = selection.fallback;
|
|
348
|
+
let switched = false;
|
|
349
|
+
const disposeFallback = childCtx.on('agent/request-error', async (payload, next) => {
|
|
350
|
+
if (payload.agent.id !== child.id || payload.signal.aborted)
|
|
351
|
+
return next();
|
|
352
|
+
const transition = selectFallbackRoute(selectionRef.current ?? { provider: selection.provider, model: selection.model }, fallback, payload.failure.code, switched);
|
|
353
|
+
// selectFallbackRoute only retries when a fallback route exists; the
|
|
354
|
+
// explicit guard narrows that fact for the compiler.
|
|
355
|
+
if (fallback !== undefined && transition.retry) {
|
|
356
|
+
switched = transition.switched;
|
|
357
|
+
selectionRef.current = transition.selection;
|
|
358
|
+
// Request recovery repeats buildRequest inside the current step; it
|
|
359
|
+
// does not re-run prompt assembly. Override that captured route too,
|
|
360
|
+
// otherwise the authorized retry would hit the failed primary again.
|
|
361
|
+
selectionRef.assembled = transition.selection;
|
|
362
|
+
await updateFallbackState(stateRoot, teamId, memberName, fallback, ctx).catch((error) => {
|
|
363
|
+
ctx.logger.warn(`t-team: failed to persist fallback route: ${String(error)}`);
|
|
364
|
+
});
|
|
365
|
+
ctx.logger.warn(`t-team: member ${child.id} switching to fallback ${fallback.provider}/${fallback.model} after ${payload.failure.code}`);
|
|
366
|
+
return { kind: 'retry' };
|
|
367
|
+
}
|
|
368
|
+
return next();
|
|
369
|
+
});
|
|
370
|
+
return () => {
|
|
371
|
+
disposeFallback();
|
|
372
|
+
disposeSelection();
|
|
373
|
+
disposeFailure();
|
|
374
|
+
};
|
|
375
|
+
});
|
|
376
|
+
return {
|
|
377
|
+
isPendingMember(agent) {
|
|
378
|
+
const parent = agent.session.header.parentSession;
|
|
379
|
+
const descriptor = foldSubagentDescriptor(sessionOwnEvents(agent.session));
|
|
380
|
+
return parent !== undefined && descriptor?.mode === 'continuable'
|
|
381
|
+
&& pending.has(pendingSelectionKey(parent, descriptor.label));
|
|
382
|
+
},
|
|
383
|
+
async withPending(parentSessionId, label, selection, operation) {
|
|
384
|
+
const key = pendingSelectionKey(parentSessionId, label);
|
|
385
|
+
if (pending.has(key)) {
|
|
386
|
+
throw new Error(`member model selection is already pending for "${label}"`);
|
|
387
|
+
}
|
|
388
|
+
pending.set(key, selection);
|
|
389
|
+
try {
|
|
390
|
+
return await operation();
|
|
391
|
+
}
|
|
392
|
+
finally {
|
|
393
|
+
pending.delete(key);
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function configuredExecutionPrompt(member, config) {
|
|
399
|
+
const prompt = member.executionPrompt?.trim() || config.executionPrompt?.trim();
|
|
400
|
+
return prompt === undefined || prompt === '' ? undefined : prompt;
|
|
401
|
+
}
|
|
402
|
+
function truncatedPersonaProtocol(protocol) {
|
|
403
|
+
if (protocol === undefined || protocol.trim() === '')
|
|
404
|
+
return '(none)';
|
|
405
|
+
if (protocol.length <= PERSONA_PROTOCOL_MAX_CHARS)
|
|
406
|
+
return protocol;
|
|
407
|
+
return `${protocol.slice(0, PERSONA_PROTOCOL_MAX_CHARS)}… [truncated]`;
|
|
408
|
+
}
|
|
409
|
+
function assignedNonTerminalCount(team, memberName) {
|
|
410
|
+
return team.tasks.filter(task => (task.assignee === memberName && !TERMINAL_TASK_STATUSES.includes(task.status))).length;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* The member's system prompt (persona), shadowing the deployment persona for
|
|
414
|
+
* that child. Self-contained: it replaces the whole persona section.
|
|
415
|
+
* Frozen at spawn: draft must already carry the Team goal and profile protocol.
|
|
416
|
+
* @param team - the team the member joined.
|
|
417
|
+
* @param member - the member record (name/role are read before spawning).
|
|
418
|
+
* @param stateDir - configured state directory, so the member can locate the
|
|
419
|
+
* team files with its own file tools.
|
|
420
|
+
*/
|
|
421
|
+
export function memberPersona(team, member, stateDir, executionPrompt) {
|
|
422
|
+
const goal = team.description?.trim() || '(not provided)';
|
|
423
|
+
const injectedPrompt = member.executionPrompt?.trim() || executionPrompt?.trim();
|
|
424
|
+
const protocol = truncatedPersonaProtocol(team.profile?.protocol);
|
|
425
|
+
return `You are ${member.name}, a member of the multi-agent team "${team.name}" running inside DeepSeek Harness T Team. The captain leads the team; you are a worker member${member.role ? ` with the role: ${member.role}` : ''}.
|
|
426
|
+
|
|
427
|
+
Team context:
|
|
428
|
+
- Team id: ${team.id}
|
|
429
|
+
- Your name inside the team (use it as \`from\`/identity): ${member.name}
|
|
430
|
+
- Team goal: ${goal}
|
|
431
|
+
- Profile protocol: ${protocol}
|
|
432
|
+
${injectedPrompt === undefined || injectedPrompt === '' ? '' : `- Execution guidance:
|
|
433
|
+
${injectedPrompt}
|
|
434
|
+
`}- The team state lives under ${stateDir}/${team.id}/ (team.json and inbox/*.jsonl). You may inspect these files read-only for diagnostics, but never edit them directly; use the t_team_* tools so JSON escaping and concurrent updates stay safe.
|
|
435
|
+
- The captain and your teammates reach you through messages. Each message you receive is a new turn: act on it and end your turn with a concise reply.
|
|
436
|
+
When you receive a task, treat the assignment prompt's dependency results as source material. Do not ignore them.
|
|
437
|
+
|
|
438
|
+
Working rules:
|
|
439
|
+
1. When you receive a task assignment, call t_team_claim_task with the task id. Keep the returned attempt_id: include it in every t_team_update_task call for that execution attempt. Then mark the task in_progress.
|
|
440
|
+
2. Work thoroughly with your available tools; do not cut corners.
|
|
441
|
+
3. When finishing a task:
|
|
442
|
+
- use status=completed only when the task's success criteria are satisfied;
|
|
443
|
+
- use status=failed when blocking findings or validation failures mean downstream work must not proceed;
|
|
444
|
+
- include a concise output in either case;
|
|
445
|
+
- a stale-attempt rejection means the captain reassigned or took over the task; stop touching that task and wait for new work.
|
|
446
|
+
claimed cannot jump to completed. Mark in_progress first, then completed or failed.
|
|
447
|
+
Include attempt_id on every update. Then send_message to captain and become idle.
|
|
448
|
+
4. Send a short report to the captain with t_team_send_message (to=captain) when you complete a task or hit a blocker.
|
|
449
|
+
5. To ask a teammate something, use t_team_send_message with to=<teammate name>; the message lands in their mailbox and wakes them directly — teammates talk to each other without the captain in the loop. The same applies to the captain (to=captain).
|
|
450
|
+
6. After your turn becomes idle, the shared task scheduler may assign your next ready task automatically. Never claim a second task while you still own unfinished work.
|
|
451
|
+
7. If you already own an open attempt (claimed or in_progress) and receive mail, treat it as guidance for that same attempt_id unless the mail explicitly tells you to stop or fail. Do not claim a new task in that turn.
|
|
452
|
+
8. Do not start a teammate's assigned task. Do not privately tell the next-stage member to start; the scheduler assigns unlocked work after you become idle.
|
|
453
|
+
9. You are a worker: do not create or delete teams, reassign tasks, or add/remove members — that is the captain's job.
|
|
454
|
+
10. Quality-gate kinds carry a contract (kind, objective, inScope, acceptance, verify). Stay inside inScope. Do not mark your own implementation as review pass. Review/requirements complete only with verdict=pass; needs_revision/reject must fail with findings. Mail is not a formal next review.`;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* The initial user message delivered when the member is created.
|
|
458
|
+
* Counts non-terminal tasks already assigned to this member on the in-memory draft.
|
|
459
|
+
* @param team - the team the member joined.
|
|
460
|
+
* @param memberName - canonical member name used to count assigned pending work.
|
|
461
|
+
*/
|
|
462
|
+
export function memberWelcome(team, memberName) {
|
|
463
|
+
const assigned = assignedNonTerminalCount(team, memberName);
|
|
464
|
+
return `You have joined the team "${team.name}" as a member. Wait for an automatic assignment or a captain message.
|
|
465
|
+
Current team status: ${team.tasks.length} task(s), ${assigned} pending task(s) assigned to you.
|
|
466
|
+
Do not start work until the scheduler or captain assigns a task in this turn.`;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Spawn one member as a durable continuable subagent of the captain and fill
|
|
470
|
+
* `member.id` with its child session id. On failure nothing is persisted.
|
|
471
|
+
* @param ctx - the plugin context (injects `subagents`).
|
|
472
|
+
* @param config - member runtime knobs.
|
|
473
|
+
* @param selections - fresh/cold child model-selection bridge.
|
|
474
|
+
* @param llmSelection - resolved provider/model/reasoning snapshot.
|
|
475
|
+
* @param captain - the exact live captain agent (the calling agent).
|
|
476
|
+
* @param team - the team record (read-only here).
|
|
477
|
+
* @param member - the member draft whose `id` is filled on success.
|
|
478
|
+
* @param stateDir - configured state directory (for the persona).
|
|
479
|
+
* @param signal - caller cancellation, forwarded to the start.
|
|
480
|
+
*/
|
|
481
|
+
export async function spawnMember(ctx, config, selections, llmSelection, captain, team, member, stateDir, signal) {
|
|
482
|
+
// Fail loud at the first use: provider registration is a sibling plugin's
|
|
483
|
+
// effect and may settle after this plugin mounts. Capability checks here
|
|
484
|
+
// mirror what startContinuable would reject, with an actionable error.
|
|
485
|
+
const provider = ctx.subagents.getProvider(config.provider);
|
|
486
|
+
if (provider === undefined) {
|
|
487
|
+
throw new Error(`t-team: no subagent provider "${config.provider}" is registered (available: ${ctx.subagents.list().join(', ') || 'none'}) — `
|
|
488
|
+
+ 'check that the subagent provider row (e.g. subagent-spawn) is mounted in the composition');
|
|
489
|
+
}
|
|
490
|
+
if (provider.prepareContinuable === undefined) {
|
|
491
|
+
throw new Error(`t-team: provider "${config.provider}" does not support continuable members`);
|
|
492
|
+
}
|
|
493
|
+
if (!provider.capabilities.persona) {
|
|
494
|
+
throw new Error(`t-team: provider "${config.provider}" cannot apply a member persona`);
|
|
495
|
+
}
|
|
496
|
+
if (!provider.capabilities.toolFilter) {
|
|
497
|
+
throw new Error(`t-team: provider "${config.provider}" cannot restrict captain-only tools for members`);
|
|
498
|
+
}
|
|
499
|
+
const label = `${MEMBER_LABEL_PREFIX}${team.id}:${member.name}`;
|
|
500
|
+
const start = await selections.withPending(captain.id, label, llmSelection, () => (ctx.subagents.startContinuable({
|
|
501
|
+
provider: config.provider,
|
|
502
|
+
label,
|
|
503
|
+
request: {
|
|
504
|
+
prompt: [{ type: 'text', text: memberWelcome(team, member.name) }],
|
|
505
|
+
parent: captain,
|
|
506
|
+
persona: memberPersona(team, member, stateDir, config.executionPrompt),
|
|
507
|
+
toolFilter: { deny: [...MEMBER_DENIED_TOOLS] },
|
|
508
|
+
agentOptions: {
|
|
509
|
+
provider: llmSelection.provider,
|
|
510
|
+
model: llmSelection.model,
|
|
511
|
+
...llmSelection.reasoningEffort === undefined
|
|
512
|
+
? {}
|
|
513
|
+
: { reasoningEffort: ReasoningEffortId(llmSelection.reasoningEffort) },
|
|
514
|
+
},
|
|
515
|
+
...config.maxDepth !== undefined ? { maxDepth: config.maxDepth } : {},
|
|
516
|
+
},
|
|
517
|
+
signal,
|
|
518
|
+
})));
|
|
519
|
+
member.id = start.childId;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Deliver one message to a member as its next FIFO turn. Best effort: a
|
|
523
|
+
* failure (member gone or not continuable) is logged and reported as `false`
|
|
524
|
+
* so the caller can decide (mailbox delivery still happened).
|
|
525
|
+
*
|
|
526
|
+
* Any team sender can route through this helper: the captain is the direct
|
|
527
|
+
* parent of every member, and the caller passes the captain's live Agent
|
|
528
|
+
* (its own when the captain calls, the registry-resolved one when a member
|
|
529
|
+
* sends) — mirroring the Claude Code mailbox model where the writer writes
|
|
530
|
+
* the target's inbox and the target picks it up on its own.
|
|
531
|
+
* @param ctx - the plugin context (injects `subagents`).
|
|
532
|
+
* @param captain - the exact live captain agent (the member's direct parent).
|
|
533
|
+
* @param childId - the member's durable child session id.
|
|
534
|
+
* @param text - the message content.
|
|
535
|
+
* @param signal - caller cancellation, forwarded to the delivery.
|
|
536
|
+
* @returns whether the member inbox accepted the message.
|
|
537
|
+
*/
|
|
538
|
+
export async function deliverToMember(ctx, captain, childId, text, signal) {
|
|
539
|
+
try {
|
|
540
|
+
await queueMemberPrompt(ctx.subagents, captain, brandedSessionId(childId), [{ type: 'text', text }], signal);
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
catch (error) {
|
|
544
|
+
ctx.logger.warn(`t-team: prompt delivery to member ${childId} failed: ${String(error)}`);
|
|
545
|
+
return false;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Request cancellation of one live member's current turn. Best effort, fire
|
|
550
|
+
* and return; the target may keep running until it observes the signal.
|
|
551
|
+
* @param ctx - the plugin context (injects `subagents`).
|
|
552
|
+
* @param captain - the exact live captain agent (the member's parent).
|
|
553
|
+
* @param childId - the member's durable child session id.
|
|
554
|
+
*/
|
|
555
|
+
export function interruptMember(ctx, captain, childId) {
|
|
556
|
+
try {
|
|
557
|
+
ctx.subagents.interrupt(brandedSessionId(childId), { kind: 'ancestor', agent: captain });
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
ctx.logger.warn(`t-team: interrupt of member ${childId} failed: ${String(error)}`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Install the missing per-child retirement boundary above Harness rc.6.
|
|
565
|
+
*
|
|
566
|
+
* Upstream `interrupt()` deliberately preserves continuable sessions and the
|
|
567
|
+
* upstream seam exposes no targeted forget/retire method. The durable
|
|
568
|
+
* T Team index therefore rejects every inbox delivery before it can cold-resume a
|
|
569
|
+
* retired member. Catalog rows deliberately remain discoverable: Harness rc.8
|
|
570
|
+
* uses the direct-child catalog to authorize historical transcript reads and
|
|
571
|
+
* `openSubagent()`, so filtering those rows would make an archived member's
|
|
572
|
+
* persisted conversation inaccessible. Exact ids keep unrelated subagents
|
|
573
|
+
* untouched while the delivery boundary still prevents further model turns.
|
|
574
|
+
*/
|
|
575
|
+
export function installRetiredMemberGuard(ctx, stateDir) {
|
|
576
|
+
guardSubagentDelivery(ctx, async (parent, childId) => {
|
|
577
|
+
const retired = await readRetiredMemberIds(join(parent.session.header.cwd ?? process.cwd(), stateDir));
|
|
578
|
+
return retired.has(childId);
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Snapshot the real driver activity for durable member ids.
|
|
583
|
+
*
|
|
584
|
+
* The team record is the membership authority, so this path intentionally no
|
|
585
|
+
* longer depends on `listChildren()`'s versioned projection shape. Harness
|
|
586
|
+
* rc.8 changed those rows to branded `SessionId` values plus residency-only
|
|
587
|
+
* `activity`; neither is needed to answer whether the live Agent driver is
|
|
588
|
+
* running, idle, or absent/ready.
|
|
589
|
+
* @param ctx - the plugin context (injects `agents`).
|
|
590
|
+
* @param memberIds - child ids restored from the durable team record.
|
|
591
|
+
* @returns child id → live activity.
|
|
592
|
+
*/
|
|
593
|
+
export function memberActivity(ctx, memberIds) {
|
|
594
|
+
const activity = new Map();
|
|
595
|
+
for (const id of memberIds) {
|
|
596
|
+
if (id === '')
|
|
597
|
+
continue;
|
|
598
|
+
const live = ctx.agents.get(brandedSessionId(id));
|
|
599
|
+
activity.set(id, live === undefined ? 'ready' : live.status);
|
|
600
|
+
}
|
|
601
|
+
return activity;
|
|
602
|
+
}
|