heylead 0.10.330__tar.gz → 0.10.332__tar.gz

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.
Files changed (347) hide show
  1. {heylead-0.10.330 → heylead-0.10.332}/AGENTS.md +2 -2
  2. {heylead-0.10.330 → heylead-0.10.332}/PKG-INFO +1 -1
  3. {heylead-0.10.330 → heylead-0.10.332}/SKILL.md +2 -2
  4. {heylead-0.10.330 → heylead-0.10.332}/clawhub/SKILL.md +2 -2
  5. {heylead-0.10.330 → heylead-0.10.332}/clawhub.json +1 -1
  6. heylead-0.10.332/docs/superpowers/specs/2026-09-09-edit-campaign-agent-flags-design.md +24 -0
  7. {heylead-0.10.330 → heylead-0.10.332}/pyproject.toml +1 -1
  8. {heylead-0.10.330 → heylead-0.10.332}/server.json +2 -2
  9. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/server.py +35 -3
  10. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/brand_strategy.py +73 -2
  11. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/edit_campaign.py +69 -1
  12. {heylead-0.10.330 → heylead-0.10.332}/.cursorrules +0 -0
  13. {heylead-0.10.330 → heylead-0.10.332}/.github/workflows/publish.yml +0 -0
  14. {heylead-0.10.330 → heylead-0.10.332}/.github/workflows/test.yml +0 -0
  15. {heylead-0.10.330 → heylead-0.10.332}/.gitignore +0 -0
  16. {heylead-0.10.330 → heylead-0.10.332}/Dockerfile +0 -0
  17. {heylead-0.10.330 → heylead-0.10.332}/LICENSE +0 -0
  18. {heylead-0.10.330 → heylead-0.10.332}/README.md +0 -0
  19. {heylead-0.10.330 → heylead-0.10.332}/clawhub/clawhub.json +0 -0
  20. {heylead-0.10.330 → heylead-0.10.332}/docs/AUDIT-2026-08.md +0 -0
  21. {heylead-0.10.330 → heylead-0.10.332}/docs/CLI_AND_DX_IMPROVEMENTS.md +0 -0
  22. {heylead-0.10.330 → heylead-0.10.332}/docs/EXPLICIT_IMPROVEMENT_PLAN.md +0 -0
  23. {heylead-0.10.330 → heylead-0.10.332}/docs/HANDOFF-2026-08-06.md +0 -0
  24. {heylead-0.10.330 → heylead-0.10.332}/docs/QUALITY_AND_SATISFACTION_ASSESSMENT.md +0 -0
  25. {heylead-0.10.330 → heylead-0.10.332}/docs/TOOL_TEST_REPORT.md +0 -0
  26. {heylead-0.10.330 → heylead-0.10.332}/docs/USER_STORY_TEST.md +0 -0
  27. {heylead-0.10.330 → heylead-0.10.332}/docs/product-listing-copy.md +0 -0
  28. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/plans/2026-08-07-cloud-sync-push.md +0 -0
  29. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/00-shared-context.md +0 -0
  30. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/01-first-degree-client.md +0 -0
  31. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/02-first-degree-backend-dashboard.md +0 -0
  32. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/03-duplicate-sends-hardening.md +0 -0
  33. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/04-reply-context-backend.md +0 -0
  34. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/05-reply-context-client.md +0 -0
  35. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/06-decision-maker-targeting.md +0 -0
  36. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/07-kb-port-and-goal-icp-match.md +0 -0
  37. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/08-stop-feedback-learning-loop.md +0 -0
  38. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/prompts/2026-09-09-quontex-feedback/README.md +0 -0
  39. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-08-23-premium-mixed-outreach-design.md +0 -0
  40. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-08-23-unanswered-lead-alerts-design.md +0 -0
  41. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-09-08-campaign-prospect-provenance-design.md +0 -0
  42. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-09-09-host-ops-playbook-design.md +0 -0
  43. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-09-09-hot-lead-closer-design.md +0 -0
  44. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-09-09-icp-research-agent-design.md +0 -0
  45. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-09-09-inspect-agent-ops-design.md +0 -0
  46. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-09-09-inspect-jobs-design.md +0 -0
  47. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-09-09-reply-exception-agent-design.md +0 -0
  48. {heylead-0.10.330 → heylead-0.10.332}/docs/superpowers/specs/2026-09-09-strategist-replan-agent-design.md +0 -0
  49. {heylead-0.10.330 → heylead-0.10.332}/llms-full.txt +0 -0
  50. {heylead-0.10.330 → heylead-0.10.332}/llms.txt +0 -0
  51. {heylead-0.10.330 → heylead-0.10.332}/scripts/find_query_contracts.py +0 -0
  52. {heylead-0.10.330 → heylead-0.10.332}/scripts/fix_stuck_prospects.py +0 -0
  53. {heylead-0.10.330 → heylead-0.10.332}/scripts/reactivate_existing_network.py +0 -0
  54. {heylead-0.10.330 → heylead-0.10.332}/scripts/rekey_unipile_account.py +0 -0
  55. {heylead-0.10.330 → heylead-0.10.332}/scripts/release.py +0 -0
  56. {heylead-0.10.330 → heylead-0.10.332}/scripts/seed_shared_directory.py +0 -0
  57. {heylead-0.10.330 → heylead-0.10.332}/scripts/test_reaction_live.py +0 -0
  58. {heylead-0.10.330 → heylead-0.10.332}/smithery.yaml +0 -0
  59. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/__init__.py +0 -0
  60. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/__main__.py +0 -0
  61. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/__init__.py +0 -0
  62. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/agent_loop.py +0 -0
  63. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/brand_strategist.py +0 -0
  64. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/brief_builder.py +0 -0
  65. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/comment_generator.py +0 -0
  66. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/context_summarizer.py +0 -0
  67. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/draft_guard.py +0 -0
  68. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/email_generator.py +0 -0
  69. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/embeddings.py +0 -0
  70. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/evidence.py +0 -0
  71. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/followup_generator.py +0 -0
  72. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/followup_schemas.py +0 -0
  73. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/hot_lead_closer.py +0 -0
  74. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/hume_client.py +0 -0
  75. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/hume_voice.py +0 -0
  76. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/icp_generator.py +0 -0
  77. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/icp_generator_v2.py +0 -0
  78. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/icp_pipeline.py +0 -0
  79. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/icp_research.py +0 -0
  80. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/icp_schemas.py +0 -0
  81. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/inbound_qualifier.py +0 -0
  82. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/ingestion/__init__.py +0 -0
  83. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/ingestion/chunker.py +0 -0
  84. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/ingestion/crawler.py +0 -0
  85. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/ingestion/store.py +0 -0
  86. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/intent.py +0 -0
  87. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/length_fixer.py +0 -0
  88. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/linkedin_enricher.py +0 -0
  89. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/llm.py +0 -0
  90. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/llm_router.py +0 -0
  91. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/llm_validator.py +0 -0
  92. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/memory_extractor.py +0 -0
  93. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/memory_formatter.py +0 -0
  94. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/message_fixer.py +0 -0
  95. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/message_generator.py +0 -0
  96. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/message_improver.py +0 -0
  97. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/message_validator.py +0 -0
  98. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/news_service.py +0 -0
  99. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/persona_cards.py +0 -0
  100. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/post_analyzer.py +0 -0
  101. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/prompt_loader.py +0 -0
  102. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/prospect_analyzer.py +0 -0
  103. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/referral_extractor.py +0 -0
  104. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/reply_agent.py +0 -0
  105. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/reply_generator.py +0 -0
  106. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/reply_pipeline.py +0 -0
  107. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/schemas.py +0 -0
  108. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/sentiment.py +0 -0
  109. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/signal_classifier.py +0 -0
  110. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/strategist_prompts.py +0 -0
  111. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/strategist_replan.py +0 -0
  112. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/strategy_prompts.py +0 -0
  113. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/targeting_recheck.py +0 -0
  114. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/vector_search.py +0 -0
  115. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/voice_analyzer.py +0 -0
  116. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ai/voice_memo_generator.py +0 -0
  117. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/author_identity.py +0 -0
  118. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/cli/__init__.py +0 -0
  119. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/cli/log_analyzer.py +0 -0
  120. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/__init__.py +0 -0
  121. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/comment_mining_collector.py +0 -0
  122. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/company_follower_collector.py +0 -0
  123. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/company_page_collector.py +0 -0
  124. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/competitor_collector.py +0 -0
  125. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/distributed_post_collector.py +0 -0
  126. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/hiring_collector.py +0 -0
  127. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/job_change_collector.py +0 -0
  128. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/keyword_collector.py +0 -0
  129. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/network_post_collector.py +0 -0
  130. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/news_collector.py +0 -0
  131. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/post_intent_collector.py +0 -0
  132. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/profile_view_collector.py +0 -0
  133. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/prospect_post_collector.py +0 -0
  134. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/collectors/watchlist_web_collector.py +0 -0
  135. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/config.py +0 -0
  136. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/constants.py +0 -0
  137. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/correlation.py +0 -0
  138. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/daemon.py +0 -0
  139. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/brazil.json +0 -0
  140. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/france.json +0 -0
  141. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/germany.json +0 -0
  142. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/india.json +0 -0
  143. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/mexico.json +0 -0
  144. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/nigeria.json +0 -0
  145. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/philippines.json +0 -0
  146. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/poland.json +0 -0
  147. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/ukraine.json +0 -0
  148. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/united_kingdom.json +0 -0
  149. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/data/country_signals/vietnam.json +0 -0
  150. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/__init__.py +0 -0
  151. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/aio.py +0 -0
  152. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/async_bridge.py +0 -0
  153. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/backup.py +0 -0
  154. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/connection_queries.py +0 -0
  155. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/global_contact_queries.py +0 -0
  156. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/post_queries.py +0 -0
  157. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/queries.py +0 -0
  158. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/schema.py +0 -0
  159. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/signal_queries.py +0 -0
  160. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/strategist_queries.py +0 -0
  161. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/db/strategy_queries.py +0 -0
  162. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/flags.py +0 -0
  163. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/formatter.py +0 -0
  164. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/guardrails.py +0 -0
  165. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/__init__.py +0 -0
  166. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/api_metrics.py +0 -0
  167. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/backend_client.py +0 -0
  168. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/chat_lookup_cache.py +0 -0
  169. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/circuit_breaker.py +0 -0
  170. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/experience.py +0 -0
  171. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/messaging.py +0 -0
  172. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/profile.py +0 -0
  173. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/profile_normalize.py +0 -0
  174. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/rate_limiter.py +0 -0
  175. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/relations.py +0 -0
  176. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/search.py +0 -0
  177. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/search_traffic.py +0 -0
  178. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/unipile.py +0 -0
  179. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/linkedin/voyager_health.py +0 -0
  180. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/logging_setup.py +0 -0
  181. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/ops_log.py +0 -0
  182. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/__init__.py +0 -0
  183. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/comment_main.json +0 -0
  184. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/filter_candidates.json +0 -0
  185. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/followup_fix.json +0 -0
  186. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/followup_message.json +0 -0
  187. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/followup_message_buy.json +0 -0
  188. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/followup_news.json +0 -0
  189. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/followup_reasoning.json +0 -0
  190. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/followup_reasoning_buy.json +0 -0
  191. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/followup_validate.json +0 -0
  192. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/followup_validate_buy.json +0 -0
  193. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/fragments/voice_rules.txt +0 -0
  194. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/message_fix.json +0 -0
  195. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/message_improve.json +0 -0
  196. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_inmail.json +0 -0
  197. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_inmail_buy.json +0 -0
  198. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_invitation.json +0 -0
  199. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_invitation_buy.json +0 -0
  200. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_job_search.json +0 -0
  201. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_response.json +0 -0
  202. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_response_buy.json +0 -0
  203. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_system.json +0 -0
  204. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_system_buy.json +0 -0
  205. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_system_partner.json +0 -0
  206. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_system_recruit.json +0 -0
  207. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_validate.json +0 -0
  208. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/outreach_validate_buy.json +0 -0
  209. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/prospect_analysis.json +0 -0
  210. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/prompts/voice_analysis.json +0 -0
  211. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/scheduler/__init__.py +0 -0
  212. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/scheduler/engine.py +0 -0
  213. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/scheduler/enqueue_gate.py +0 -0
  214. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/scheduler/executors.py +0 -0
  215. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/scheduler/leader.py +0 -0
  216. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/scheduler/planner.py +0 -0
  217. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/scheduler/trace.py +0 -0
  218. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/__init__.py +0 -0
  219. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/action_health.py +0 -0
  220. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/action_timeline.py +0 -0
  221. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/action_verifier.py +0 -0
  222. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/anomaly_detector.py +0 -0
  223. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/brand_service.py +0 -0
  224. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/calendar_booker.py +0 -0
  225. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/campaign_optimizer.py +0 -0
  226. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/campaign_refill_service.py +0 -0
  227. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/campaign_spawner.py +0 -0
  228. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/channel_selector.py +0 -0
  229. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/cloud_sync.py +0 -0
  230. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/communication_strategist.py +0 -0
  231. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/company_name.py +0 -0
  232. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/connection_sync.py +0 -0
  233. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/conversation_enricher.py +0 -0
  234. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/daily_digest.py +0 -0
  235. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/dedup_service.py +0 -0
  236. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/directory_card.py +0 -0
  237. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/dm_connection_guard.py +0 -0
  238. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/engagement_verifier.py +0 -0
  239. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/experiment_service.py +0 -0
  240. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/fit_gate.py +0 -0
  241. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/health_score.py +0 -0
  242. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/hot_lead_closer.py +0 -0
  243. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/hubspot_service.py +0 -0
  244. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/icp_match_scorer.py +0 -0
  245. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/icp_research.py +0 -0
  246. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/icp_search.py +0 -0
  247. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/inbound_helpers.py +0 -0
  248. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/inbound_pipeline.py +0 -0
  249. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/inbound_policy.py +0 -0
  250. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/inbound_relationship.py +0 -0
  251. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/inbound_service.py +0 -0
  252. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/inbox_match.py +0 -0
  253. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/intent_signals.py +0 -0
  254. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/live_thread_enroll.py +0 -0
  255. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/outreach_channel.py +0 -0
  256. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/own_identity.py +0 -0
  257. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/own_profile_sync.py +0 -0
  258. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/pattern_detector.py +0 -0
  259. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/post_research_service.py +0 -0
  260. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/process_caches.py +0 -0
  261. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/profile_signals.py +0 -0
  262. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/project_brief.py +0 -0
  263. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/prospect_email.py +0 -0
  264. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/prospect_timezone.py +0 -0
  265. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/provider_id_repair.py +0 -0
  266. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/provider_id_resolver.py +0 -0
  267. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/recover_stuck_outreaches.py +0 -0
  268. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/referral_enroll.py +0 -0
  269. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/reply_agent.py +0 -0
  270. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/revenue_estimator.py +0 -0
  271. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/search_account_resolver.py +0 -0
  272. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/seed_shared_directory.py +0 -0
  273. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/session_health.py +0 -0
  274. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/signal_activator.py +0 -0
  275. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/signal_analytics.py +0 -0
  276. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/signal_linker.py +0 -0
  277. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/signal_optimizer.py +0 -0
  278. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/signal_scorer.py +0 -0
  279. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/signal_service.py +0 -0
  280. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/strategist_replan.py +0 -0
  281. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/strategy_engine.py +0 -0
  282. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/tabular_reader.py +0 -0
  283. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/timezone_resolver.py +0 -0
  284. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/unanswered_lead_alerts.py +0 -0
  285. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/services/unipile_email.py +0 -0
  286. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/textutil.py +0 -0
  287. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tier.py +0 -0
  288. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/timeutil.py +0 -0
  289. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/__init__.py +0 -0
  290. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/account.py +0 -0
  291. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/analytics.py +0 -0
  292. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/archive_campaign.py +0 -0
  293. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/backfill_inbox.py +0 -0
  294. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/book_meeting.py +0 -0
  295. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/campaign.py +0 -0
  296. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/campaign_control.py +0 -0
  297. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/campaign_report.py +0 -0
  298. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/check_replies.py +0 -0
  299. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/close_outreach.py +0 -0
  300. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/compare_campaigns.py +0 -0
  301. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/contacts.py +0 -0
  302. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/create_campaign.py +0 -0
  303. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/create_post.py +0 -0
  304. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/crm_sync.py +0 -0
  305. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/delete_campaign.py +0 -0
  306. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/delete_message.py +0 -0
  307. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/dismiss_lead.py +0 -0
  308. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/emergency_stop.py +0 -0
  309. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/engage_prospect.py +0 -0
  310. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/experiment_loop.py +0 -0
  311. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/export_campaign.py +0 -0
  312. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/generate_icp.py +0 -0
  313. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/generate_send.py +0 -0
  314. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/icp.py +0 -0
  315. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/import_prospects.py +0 -0
  316. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/inbox.py +0 -0
  317. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/inspect.py +0 -0
  318. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/manage_watchlist.py +0 -0
  319. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/network.py +0 -0
  320. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/organization.py +0 -0
  321. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/partner_followup.py +0 -0
  322. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/profile_editor.py +0 -0
  323. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/profile_history.py +0 -0
  324. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/profile_signals.py +0 -0
  325. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/prospect.py +0 -0
  326. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/prospect_timeline.py +0 -0
  327. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/reply_to_prospect.py +0 -0
  328. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/retry_failed.py +0 -0
  329. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/scheduler.py +0 -0
  330. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/scheduler_status.py +0 -0
  331. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/send_email.py +0 -0
  332. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/send_followup.py +0 -0
  333. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/send_inmail.py +0 -0
  334. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/send_message.py +0 -0
  335. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/send_voice_memo.py +0 -0
  336. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/setup_profile.py +0 -0
  337. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/show_conversation.py +0 -0
  338. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/show_signals.py +0 -0
  339. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/show_status.py +0 -0
  340. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/show_strategy.py +0 -0
  341. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/signal_report.py +0 -0
  342. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/signals.py +0 -0
  343. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/skip_prospect.py +0 -0
  344. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/suggest_next_action.py +0 -0
  345. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/switch_account.py +0 -0
  346. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tools/unlink_account.py +0 -0
  347. {heylead-0.10.330 → heylead-0.10.332}/src/heylead/tracing.py +0 -0
@@ -41,7 +41,7 @@ Never paste model-authored text as the LinkedIn message. The send tools generate
41
41
 
42
42
  Never launch a draft unless the user asked.
43
43
 
44
- In-process agents default to observe. Do not invent MCP kwargs to turn them to act.
44
+ In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, or `edit_campaign(enable_hot_lead_closer="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
45
45
 
46
46
  ## Authentication
47
47
 
@@ -70,7 +70,7 @@ In-process agents default to observe. Do not invent MCP kwargs to turn them to a
70
70
  |------|-------------|
71
71
  | `create_campaign` | Create an outreach campaign (as a draft) from a natural language description, with ICP-based targeting |
72
72
  | `campaign` | Campaign lifecycle — launch, pause, resume, archive, delete, emergency stop, retry failed |
73
- | `edit_campaign` | Update campaign name, mode, booking link, offerings, case studies, or messaging preferences |
73
+ | `edit_campaign` | Update campaign name, mode, booking link, offerings, case studies, messaging preferences, or agent act flags |
74
74
  | `import_prospects` | Import prospects from CSV data into a campaign |
75
75
 
76
76
  ### Outreach Execution
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: heylead
3
- Version: 0.10.330
3
+ Version: 0.10.332
4
4
  Summary: MCP-native autonomous LinkedIn SDR. Your AI sales rep, one command to fill your pipeline.
5
5
  Project-URL: Homepage, https://github.com/D4umak/heylead
6
6
  Project-URL: Repository, https://github.com/D4umak/heylead
@@ -85,7 +85,7 @@ Never paste model-authored text as the LinkedIn message. The send tools generate
85
85
 
86
86
  Never launch a draft unless the user asked.
87
87
 
88
- In-process agents default to observe. Do not invent MCP kwargs to turn them to act.
88
+ In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, or `edit_campaign(enable_hot_lead_closer="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
89
89
 
90
90
  ## Safety Model
91
91
 
@@ -103,7 +103,7 @@ Campaigns are created as drafts and only start when explicitly launched. Every s
103
103
  | `profile_signals` | Compile a targeting request (country ties, interests) into LinkedIn recall queries and profile evidence |
104
104
  | `create_campaign` | Find prospects and build an outreach campaign (as a draft) |
105
105
  | `campaign` | Launch, pause, resume, archive, delete, emergency stop, retry failed |
106
- | `edit_campaign` | Update name, mode, booking link, preferences |
106
+ | `edit_campaign` | Update name, mode, booking link, preferences, or agent act flags |
107
107
  | `import_prospects` | Import prospects from CSV |
108
108
  | `generate_and_send` | Send personalized connection invitations |
109
109
  | `send_message` | Follow-up DMs, replies, and voice memos |
@@ -88,7 +88,7 @@ Never paste model-authored text as the LinkedIn message. The send tools generate
88
88
 
89
89
  Never launch a draft unless the user asked.
90
90
 
91
- In-process agents default to observe. Do not invent MCP kwargs to turn them to act.
91
+ In-process agents default to observe. Turn act on with `edit_campaign(enable_reply_agent="on")`, `edit_campaign(enable_strategist_replan_agent="on")`, or `edit_campaign(enable_hot_lead_closer="on")`. Use `"observe"` to return to logging-only, `"off"` to disable.
92
92
 
93
93
  ## Safety Model
94
94
 
@@ -106,7 +106,7 @@ Campaigns are created as drafts and only start when explicitly launched. Every s
106
106
  | `profile_signals` | Compile a targeting request (country ties, interests) into LinkedIn recall queries and profile evidence |
107
107
  | `create_campaign` | Find prospects and build an outreach campaign (as a draft) |
108
108
  | `campaign` | Launch, pause, resume, archive, delete, emergency stop, retry failed |
109
- | `edit_campaign` | Update name, mode, booking link, preferences |
109
+ | `edit_campaign` | Update name, mode, booking link, preferences, or agent act flags |
110
110
  | `import_prospects` | Import prospects from CSV |
111
111
  | `generate_and_send` | Send personalized connection invitations |
112
112
  | `send_message` | Follow-up DMs, replies, and voice memos |
@@ -17,7 +17,7 @@
17
17
  "icp",
18
18
  "campaign-management"
19
19
  ],
20
- "version": "0.10.330",
20
+ "version": "0.10.332",
21
21
  "license": "MIT",
22
22
  "author": {
23
23
  "name": "HeyLead",
@@ -0,0 +1,24 @@
1
+ # edit_campaign agent flags
2
+
3
+ Date: 2026-09-09
4
+
5
+ The four in-process agents default to observe. Act lives on campaign config (`enable_reply_agent`, `enable_strategist_replan_agent`, `enable_hot_lead_closer`), but `edit_campaign` does not accept those kwargs. Host docs told the model not to invent them.
6
+
7
+ This spec wires the three campaign flags. ICP research stays an account setting.
8
+
9
+ ## Goals
10
+
11
+ - `edit_campaign(enable_reply_agent="", enable_strategist_replan_agent="", enable_hot_lead_closer="")`
12
+ - Values: `on` | `off` | `observe`. Empty = no change.
13
+ - **on** → write the enable key as a boolean `True` (same style as `enable_auto_replies`). Mode readers return `act`.
14
+ - **off** → write `False`. Mode readers return `off`.
15
+ - **observe** → delete the enable key and the matching `*_mode` key so unset = observe.
16
+ - Invalid value rejected; config unchanged.
17
+ - MCP wrapper exposes the same three parameters.
18
+ - Playbook / MCP instructions show the real calls instead of “do not invent kwargs”.
19
+
20
+ ## Non-goals
21
+
22
+ - `enable_icp_research_agent` (settings, not campaign config).
23
+ - New MCP tool.
24
+ - Changing default observe behavior.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "heylead"
7
- version = "0.10.330"
7
+ version = "0.10.332"
8
8
  description = "MCP-native autonomous LinkedIn SDR. Your AI sales rep, one command to fill your pipeline."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.D4umak/heylead",
4
4
  "title": "HeyLead \u2014 Autonomous LinkedIn SDR",
5
5
  "description": "Autonomous LinkedIn SDR \u2014 voice-matched outreach, ICP generation, and campaign management.",
6
- "version": "0.10.330",
6
+ "version": "0.10.332",
7
7
  "websiteUrl": "https://github.com/D4umak/heylead",
8
8
  "repository": {
9
9
  "url": "https://github.com/D4umak/heylead",
@@ -13,7 +13,7 @@
13
13
  {
14
14
  "registryType": "pypi",
15
15
  "identifier": "heylead",
16
- "version": "0.10.330",
16
+ "version": "0.10.332",
17
17
  "runtimeHint": "uvx",
18
18
  "transport": {
19
19
  "type": "stdio"
@@ -28,6 +28,20 @@ from .ops_log import run_traced
28
28
  _CHANGELOG = """\
29
29
  # HeyLead Changelog
30
30
 
31
+ ## v0.10.332 (2026-09-09)
32
+ - New: brand_strategy(action="set_headline", focus="...") sets the LinkedIn
33
+ headline to exactly the text you pass. execute and makeover both write a
34
+ model-generated headline, and the headline A/B test is off, so a headline
35
+ you had already decided on could not be applied from HeyLead at all. The
36
+ write goes through the normal profile-change path, so it is logged and
37
+ restorable with profile(action="restore"), and it is refused over the
38
+ 220-character LinkedIn limit instead of being silently clipped (#263)
39
+
40
+ ## v0.10.331 (2026-09-09)
41
+ - New: edit_campaign can turn the reply, strategist, and closer agents
42
+ to act, off, or observe. Hosts no longer have to invent those kwargs
43
+ (#272)
44
+
31
45
  ## v0.10.330 (2026-09-09)
32
46
  - New: inspect(action='jobs') lists pending scheduler jobs and recent
33
47
  gated-job refusals, and explains observe / cloud ownership when the
@@ -1218,8 +1232,11 @@ mcp = FastMCP(
1218
1232
  " was skipped, call inspect() first — it never writes. A hold →\n"
1219
1233
  " prospect(action='conversation') then send_message(action='reply').\n"
1220
1234
  " Never paste model-authored text as the LinkedIn message; the send\n"
1221
- " tools generate it. Agents default to observe; do not invent\n"
1222
- " edit_campaign kwargs to flip them to act.\n"
1235
+ " tools generate it. Agents default to observe. Turn act on with\n"
1236
+ " edit_campaign(enable_reply_agent='on'),\n"
1237
+ " edit_campaign(enable_strategist_replan_agent='on'), or\n"
1238
+ " edit_campaign(enable_hot_lead_closer='on'). Use 'observe' to\n"
1239
+ " return to logging-only, 'off' to disable.\n"
1223
1240
  " - book_meeting() — put an agreed call on your Google Calendar and invite them\n"
1224
1241
  " - suggest_next_action() — AI-recommended next step\n"
1225
1242
  " - analytics(action='report') — detailed analytics with outcomes and stale lead warnings\n"
@@ -2038,6 +2055,9 @@ async def edit_campaign(
2038
2055
  enable_auto_replies: str = "",
2039
2056
  enable_invitations: str = "",
2040
2057
  enable_discovery: str = "",
2058
+ enable_reply_agent: str = "",
2059
+ enable_strategist_replan_agent: str = "",
2060
+ enable_hot_lead_closer: str = "",
2041
2061
  engagement_mode: str = "",
2042
2062
  max_followups: int = 0,
2043
2063
  followup_delay_days: str = "",
@@ -2088,6 +2108,12 @@ async def edit_campaign(
2088
2108
  When off, campaign only DMs existing connections (no invitations sent).
2089
2109
  enable_discovery: Auto-find and enrol new prospects: "on" or "off".
2090
2110
  Turn off for curated campaigns with a fixed, hand-picked list.
2111
+ enable_reply_agent: Reply exception agent: "on" (act), "off", or
2112
+ "observe". Empty keeps the current value. Unset defaults to observe.
2113
+ enable_strategist_replan_agent: Strategist replan: "on", "off", or
2114
+ "observe". Empty keeps the current value.
2115
+ enable_hot_lead_closer: Hot-lead closer: "on", "off", or "observe".
2116
+ Empty keeps the current value.
2091
2117
  engagement_mode: Engagement style: "auto" (30% react / 70% comment),
2092
2118
  "comment_only", or "react_only".
2093
2119
  max_followups: Max follow-up messages (1-5). 0 to keep current.
@@ -2133,6 +2159,9 @@ async def edit_campaign(
2133
2159
  enable_auto_replies=enable_auto_replies,
2134
2160
  enable_invitations=enable_invitations,
2135
2161
  enable_discovery=enable_discovery,
2162
+ enable_reply_agent=enable_reply_agent,
2163
+ enable_strategist_replan_agent=enable_strategist_replan_agent,
2164
+ enable_hot_lead_closer=enable_hot_lead_closer,
2136
2165
  engagement_mode=engagement_mode,
2137
2166
  max_followups=max_followups,
2138
2167
  followup_delay_days=followup_delay_days,
@@ -2433,8 +2462,11 @@ async def brand_strategy(
2433
2462
  "upload_photo" — Upload a profile photo (provide file_path or base64 data)
2434
2463
  "upload_cover" — Upload a cover/banner photo (same input as upload_photo)
2435
2464
  "set_link" — Set custom CTA link on profile (pass URL via focus param)
2465
+ "set_headline" — Set the headline to exact text (pass the headline via focus).
2466
+ Use this when the user has already decided the wording; "execute" and
2467
+ "makeover" write a model-generated headline instead.
2436
2468
  focus: Focus area for analyze/plan ("headline", "summary", "content", "engagement", ""),
2437
- or URL string for set_link action.
2469
+ URL string for set_link, or the literal headline text for set_headline.
2438
2470
  photo: File path or base64-encoded image for upload_photo / upload_cover actions.
2439
2471
  """
2440
2472
  from .tools.brand_strategy import run_brand_strategy
@@ -46,6 +46,9 @@ from ..db.async_bridge import run_db
46
46
 
47
47
  logger = logging.getLogger(__name__)
48
48
 
49
+ # LinkedIn truncates a headline past this, so refuse rather than silently clip.
50
+ HEADLINE_MAX_CHARS = 220
51
+
49
52
 
50
53
  async def run_brand_strategy(
51
54
  action: str = "analyze",
@@ -80,6 +83,8 @@ async def run_brand_strategy(
80
83
  return await _handle_upload_cover(account_id, photo)
81
84
  elif action == "set_link":
82
85
  return await _handle_set_link(account_id, focus)
86
+ elif action == "set_headline":
87
+ return await _handle_set_headline(account_id, focus)
83
88
  elif action == "makeover":
84
89
  return await _handle_makeover(account_id)
85
90
  elif action == "photo_enhance":
@@ -98,6 +103,7 @@ async def run_brand_strategy(
98
103
  ' brand_strategy(action="upload_photo") — Upload profile photo\n'
99
104
  ' brand_strategy(action="upload_cover") — Upload cover photo\n'
100
105
  ' brand_strategy(action="set_link", focus="https://...") — Set custom CTA link\n'
106
+ ' brand_strategy(action="set_headline", focus="Your exact headline") — Set the headline verbatim\n'
101
107
  ' brand_strategy(action="makeover") — One-click full profile optimization\n'
102
108
  ' brand_strategy(action="photo_enhance") — Auto-enhance profile photo settings\n'
103
109
  ' brand_strategy(action="test_headline", focus="Variant A | Variant B") — Start headline A/B test\n'
@@ -1415,6 +1421,70 @@ async def _handle_set_link(account_id: str, url: str) -> str:
1415
1421
  return f"Failed to set custom link: {e}"
1416
1422
 
1417
1423
 
1424
+ async def _handle_set_headline(account_id: str, text: str) -> str:
1425
+ """Set the headline to exactly *text*.
1426
+
1427
+ ``execute`` and ``makeover`` write a model-generated headline. This
1428
+ writes the words the user chose, unchanged, so a headline decided
1429
+ outside HeyLead does not have to be pasted into LinkedIn by hand.
1430
+ """
1431
+ profile = await run_db(get_setting, "profile", {})
1432
+ current = profile.get("headline", "") or "(not set)"
1433
+
1434
+ headline = (text or "").strip()
1435
+ if not headline:
1436
+ return (
1437
+ "Set your LinkedIn headline to exact text:\n\n"
1438
+ ' brand_strategy(action="set_headline", focus="Your exact headline")\n\n'
1439
+ f" Current: {current}\n\n"
1440
+ f"The text is written verbatim, up to {HEADLINE_MAX_CHARS} characters.\n"
1441
+ 'For a generated headline instead, use brand_strategy(action="makeover").'
1442
+ )
1443
+
1444
+ if len(headline) > HEADLINE_MAX_CHARS:
1445
+ return (
1446
+ f"Headline is {len(headline)} characters, over the LinkedIn limit "
1447
+ f"of {HEADLINE_MAX_CHARS}.\n\n"
1448
+ f"Trim {len(headline) - HEADLINE_MAX_CHARS} characters and try again. "
1449
+ "Nothing was changed."
1450
+ )
1451
+
1452
+ if headline == (profile.get("headline") or ""):
1453
+ return f"Headline is already:\n\n {headline}\n\nNothing to change."
1454
+
1455
+ from .profile_editor import apply_profile_change
1456
+
1457
+ provider_id = profile.get("provider_id", "")
1458
+
1459
+ try:
1460
+ client = get_linkedin_client()
1461
+ result = await apply_profile_change(
1462
+ client, account_id, provider_id, "headline", headline,
1463
+ source="brand_strategy",
1464
+ )
1465
+ await client.close()
1466
+ except Exception as e:
1467
+ return f"Failed to set headline: {e}"
1468
+
1469
+ if not result.get("success"):
1470
+ error = result.get("error", "Unknown error")
1471
+ return f"Failed to set headline: {error}"
1472
+
1473
+ await run_db(
1474
+ log_action,
1475
+ "brand_headline_set",
1476
+ details={"headline": headline, "previous": current},
1477
+ )
1478
+ return (
1479
+ "Headline updated.\n\n"
1480
+ f" Before: {current}\n"
1481
+ f" After: {headline}\n\n"
1482
+ f" {len(headline)}/{HEADLINE_MAX_CHARS} characters\n\n"
1483
+ 'Roll back with profile(action="history", field="headline") '
1484
+ 'then profile(action="restore", change_id="...").'
1485
+ )
1486
+
1487
+
1418
1488
  async def _compute_current_health(ssi_data: dict[str, Any], campaign_stats: dict[str, Any]):
1419
1489
  """Compute current health score from available data."""
1420
1490
  daily_record = await run_db(get_rate_limit_today)
@@ -1697,8 +1767,9 @@ async def _handle_test_headline(focus: str) -> str:
1697
1767
  "The test could not attribute an invitation to the headline it went "
1698
1768
  "out under, so it changed your real LinkedIn headline without ever "
1699
1769
  "being able to compare the two variants.\n\n"
1700
- "Your headline is untouched. Edit it directly with "
1701
- 'brand_strategy(action="makeover") or on LinkedIn.'
1770
+ "Your headline is untouched. Set it directly with "
1771
+ 'brand_strategy(action="set_headline", focus="...") for exact text, '
1772
+ 'or brand_strategy(action="makeover") for a generated one.'
1702
1773
  )
1703
1774
 
1704
1775
  if not focus or "|" not in focus:
@@ -17,6 +17,12 @@ logger = logging.getLogger(__name__)
17
17
  # Valid values for new settings
18
18
  _VALID_ENGAGEMENT_MODES = frozenset({"auto", "comment_only", "react_only"})
19
19
  _VALID_ACTIVE_DAYS = frozenset(range(7)) # 0=Mon ... 6=Sun
20
+ _VALID_AGENT_FLAGS = frozenset({"on", "off", "observe"})
21
+ _AGENT_FLAG_SPECS = (
22
+ ("enable_reply_agent", "reply_agent_mode", "Reply agent"),
23
+ ("enable_strategist_replan_agent", "strategist_replan_mode", "Strategist replan"),
24
+ ("enable_hot_lead_closer", "hot_lead_closer_mode", "Hot-lead closer"),
25
+ )
20
26
 
21
27
 
22
28
  async def run_edit_campaign(
@@ -63,6 +69,10 @@ async def run_edit_campaign(
63
69
  active_days: str = "",
64
70
  # Message stance
65
71
  campaign_intent: str = "",
72
+ # In-process agents (observe is the default when unset)
73
+ enable_reply_agent: str = "",
74
+ enable_strategist_replan_agent: str = "",
75
+ enable_hot_lead_closer: str = "",
66
76
  ) -> str:
67
77
  """Edit a campaign's settings.
68
78
 
@@ -108,6 +118,12 @@ async def run_edit_campaign(
108
118
  send_in_business_hours: Respect prospect's business hours: "on" or "off".
109
119
  active_days: Active send days as comma-separated numbers (0=Mon, 6=Sun).
110
120
  E.g., "0,1,2,3,4" for weekdays. Leave empty to keep current.
121
+ enable_reply_agent: Reply exception agent: "on" (act), "off", or
122
+ "observe". Empty keeps the current value. Unset defaults to observe.
123
+ enable_strategist_replan_agent: Strategist replan agent: "on", "off",
124
+ or "observe". Empty keeps the current value.
125
+ enable_hot_lead_closer: Hot-lead closer: "on", "off", or "observe".
126
+ Empty keeps the current value.
111
127
  """
112
128
 
113
129
  # ── Pre-checks ──
@@ -134,13 +150,16 @@ async def run_edit_campaign(
134
150
  bool(inmail_fallback) or inmail_fallback_days > 0 or bool(inmail_first_touch)
135
151
  )
136
152
  has_timing_settings = bool(send_in_business_hours) or bool(active_days)
153
+ has_agent_settings = any([
154
+ enable_reply_agent, enable_strategist_replan_agent, enable_hot_lead_closer,
155
+ ])
137
156
 
138
157
  has_any = (
139
158
  name or mode or booking_link or voice_mode
140
159
  or has_context_fields or has_voice_settings or open_to_work_mode
141
160
  or has_toggle_settings or has_engagement_settings
142
161
  or has_followup_settings or has_invite_settings or has_inmail_settings
143
- or has_timing_settings or campaign_intent
162
+ or has_timing_settings or campaign_intent or has_agent_settings
144
163
  )
145
164
 
146
165
  if not has_any:
@@ -166,6 +185,11 @@ async def run_edit_campaign(
166
185
  " enable_invitations: on or off\n"
167
186
  " enable_discovery: on or off\n"
168
187
  "\n"
188
+ " In-process agents (default observe):\n"
189
+ " enable_reply_agent: on, off, or observe\n"
190
+ " enable_strategist_replan_agent: on, off, or observe\n"
191
+ " enable_hot_lead_closer: on, off, or observe\n"
192
+ "\n"
169
193
  " Engagement:\n"
170
194
  " engagement_mode: auto, comment_only, or react_only\n"
171
195
  "\n"
@@ -237,6 +261,16 @@ async def run_edit_campaign(
237
261
  if val and val not in ("on", "off"):
238
262
  return f"Invalid {label}: '{val}'. Must be 'on' or 'off'."
239
263
 
264
+ for label, val in [
265
+ ("enable_reply_agent", enable_reply_agent),
266
+ ("enable_strategist_replan_agent", enable_strategist_replan_agent),
267
+ ("enable_hot_lead_closer", enable_hot_lead_closer),
268
+ ]:
269
+ if val and val not in _VALID_AGENT_FLAGS:
270
+ return (
271
+ f"Invalid {label}: '{val}'. Must be 'on', 'off', or 'observe'."
272
+ )
273
+
240
274
  # ── Validate engagement_mode ──
241
275
  if engagement_mode and engagement_mode not in _VALID_ENGAGEMENT_MODES:
242
276
  return (
@@ -390,6 +424,40 @@ async def run_edit_campaign(
390
424
  label = _TOGGLE_LABELS[key]
391
425
  change_descriptions.append(f"{label}: {'on' if old_bool else 'off'} -> {val}")
392
426
 
427
+ # ── In-process agents (on=act, off, observe=unset) ──
428
+ from ..services.hot_lead_closer import hot_lead_closer_mode
429
+ from ..services.reply_agent import reply_agent_mode
430
+ from ..services.strategist_replan import strategist_replan_mode
431
+
432
+ _agent_readers = {
433
+ "enable_reply_agent": reply_agent_mode,
434
+ "enable_strategist_replan_agent": strategist_replan_mode,
435
+ "enable_hot_lead_closer": hot_lead_closer_mode,
436
+ }
437
+ _agent_values = {
438
+ "enable_reply_agent": enable_reply_agent,
439
+ "enable_strategist_replan_agent": enable_strategist_replan_agent,
440
+ "enable_hot_lead_closer": enable_hot_lead_closer,
441
+ }
442
+ for key, mode_key, label in _AGENT_FLAG_SPECS:
443
+ val = _agent_values[key]
444
+ if not val:
445
+ continue
446
+ mode_of = _agent_readers[key]
447
+ old = mode_of(config)
448
+ if val == "observe":
449
+ config.pop(key, None)
450
+ config.pop(mode_key, None)
451
+ elif val == "on":
452
+ config[key] = True
453
+ config.pop(mode_key, None)
454
+ else:
455
+ config[key] = False
456
+ config.pop(mode_key, None)
457
+ new = mode_of(config)
458
+ if old != new:
459
+ change_descriptions.append(f"{label}: {old} -> {new}")
460
+
393
461
  # ── Engagement mode ──
394
462
  if engagement_mode:
395
463
  old_em = config.get("engagement_mode", "auto")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes