fusesell 1.2.8__tar.gz → 1.2.9__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.

Potentially problematic release.


This version of fusesell might be problematic. Click here for more details.

Files changed (43) hide show
  1. {fusesell-1.2.8 → fusesell-1.2.9}/CHANGELOG.md +242 -231
  2. {fusesell-1.2.8/fusesell.egg-info → fusesell-1.2.9}/PKG-INFO +1 -1
  3. {fusesell-1.2.8 → fusesell-1.2.9/fusesell.egg-info}/PKG-INFO +1 -1
  4. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/__init__.py +1 -1
  5. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/stages/initial_outreach.py +78 -4
  6. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/utils/event_scheduler.py +42 -14
  7. {fusesell-1.2.8 → fusesell-1.2.9}/pyproject.toml +1 -1
  8. {fusesell-1.2.8 → fusesell-1.2.9}/LICENSE +0 -0
  9. {fusesell-1.2.8 → fusesell-1.2.9}/MANIFEST.in +0 -0
  10. {fusesell-1.2.8 → fusesell-1.2.9}/README.md +0 -0
  11. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell.egg-info/SOURCES.txt +0 -0
  12. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell.egg-info/dependency_links.txt +0 -0
  13. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell.egg-info/entry_points.txt +0 -0
  14. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell.egg-info/requires.txt +0 -0
  15. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell.egg-info/top_level.txt +0 -0
  16. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell.py +0 -0
  17. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/api.py +0 -0
  18. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/cli.py +0 -0
  19. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/config/__init__.py +0 -0
  20. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/config/prompts.py +0 -0
  21. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/config/settings.py +0 -0
  22. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/pipeline.py +0 -0
  23. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/stages/__init__.py +0 -0
  24. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/stages/base_stage.py +0 -0
  25. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/stages/data_acquisition.py +0 -0
  26. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/stages/data_preparation.py +0 -0
  27. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/stages/follow_up.py +0 -0
  28. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/stages/lead_scoring.py +0 -0
  29. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/tests/conftest.py +0 -0
  30. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/tests/test_api.py +0 -0
  31. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/tests/test_cli.py +0 -0
  32. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/tests/test_data_manager_products.py +0 -0
  33. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/tests/test_data_manager_sales_process.py +0 -0
  34. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/tests/test_data_manager_teams.py +0 -0
  35. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/utils/__init__.py +0 -0
  36. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/utils/birthday_email_manager.py +0 -0
  37. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/utils/data_manager.py +0 -0
  38. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/utils/llm_client.py +0 -0
  39. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/utils/logger.py +0 -0
  40. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/utils/timezone_detector.py +0 -0
  41. {fusesell-1.2.8 → fusesell-1.2.9}/fusesell_local/utils/validators.py +0 -0
  42. {fusesell-1.2.8 → fusesell-1.2.9}/requirements.txt +0 -0
  43. {fusesell-1.2.8 → fusesell-1.2.9}/setup.cfg +0 -0
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to FuseSell Local will be documented in this file.
4
4
 
5
+ # [1.2.9] - 2025-10-24
6
+
7
+ ### Changed
8
+ - Primary sales rep metadata from gs_team_rep now flows into draft prompts, reminders, and signatures so outreach reflects the configured sender.
9
+ - Reminder scheduling stores the Unix timestamp (cron_ts) alongside the ISO string for easier downstream filtering.
10
+ - Greeting sanitizer standardises the first paragraph and removes duplicate salutations while keeping HTML formatting intact.
11
+
12
+ ### Fixed
13
+ - Removed [Your ...] placeholder leftovers inside LLM responses and ensured drafts remain valid HTML even when the model mixes plain text and bullet lists.
14
+ - Reminder creation no longer fails when the data acquisition stage supplies the email address, and follow-up reminders inherit the same customer metadata.
15
+
5
16
  # [1.2.8] - 2025-10-24
6
17
 
7
18
  ### Changed
@@ -57,7 +68,7 @@ All notable changes to FuseSell Local will be documented in this file.
57
68
 
58
69
  ### Fixed
59
70
  - Default team settings seeding now targets the `gs_team_*` columns, preventing initialization failures on fresh databases.
60
-
71
+
61
72
  # [1.2.1] - 2025-10-21
62
73
 
63
74
  ### Changed
@@ -71,234 +82,234 @@ All notable changes to FuseSell Local will be documented in this file.
71
82
  ### Added
72
83
  - Packaged CLI access via `FuseSellCLI` export to support embedded runtimes and automated tests.
73
84
  - pytest coverage (`fusesell_local/tests/test_cli.py`) ensuring the CLI dry-run path remains stable.
74
-
75
- ### Changed
76
- - Distribution renamed to `fusesell` to align with upcoming PyPI publication; console entry point now resolves to `fusesell_local.cli:main`.
77
- - CLI implementation moved into `fusesell_local/cli.py`, with top-level `fusesell.py` delegating for backward compatibility.
78
- - Documentation refreshed to instruct `pip install fusesell` and demonstrate programmatic CLI reuse.
79
- - Published version `1.2.0` to PyPI under the `fusesell` distribution name.
80
-
81
- ### Fixed
82
- - Ensured package metadata includes the CLI module so installations via pip expose the `fusesell` console script.
83
-
84
- ## [1.1.0] - 2025-10-20
85
-
86
- ### Added
87
- - Library-first API (`fusesell_local.api`) exposing `build_config`, `execute_pipeline`, and supporting helpers for embedding FuseSell in external runtimes.
88
- - Public exports in `fusesell_local.__init__` so consumers can import `FuseSellPipeline` and the new helpers directly.
89
- - Programmatic configuration validation error (`ConfigValidationError`) for clearer failures in host applications.
90
-
91
- ### Changed
92
- - CLI now delegates configuration/build/validation/logging to the shared library utilities, ensuring consistent behaviour across CLI and embedded usage.
93
- - Pipeline context now forwards scheduling preferences (timezone, send_immediately, business hour fields) from configuration to stages.
94
-
95
- ### Fixed
96
- - Continuation validation correctly requires `selected_draft_id` when performing `draft_rewrite` or `send` actions.
97
-
98
- ## [1.0.0] - 2025-01-07
99
-
100
- ### Added - Core Infrastructure Complete
101
-
102
- #### CLI Interface
103
- - Complete command-line interface with 25+ configuration options
104
- - Comprehensive argument validation and error handling
105
- - Multiple output formats (JSON, YAML, text)
106
- - Dry-run mode for safe testing
107
- - Process continuation support for resuming executions
108
-
109
- #### Pipeline Engine
110
- - Full pipeline orchestration with stage control
111
- - Business logic validation extracted from original YAML workflows
112
- - Sequential stage execution with data flow management
113
- - Human-in-the-loop controls and approval points
114
- - Comprehensive error handling and recovery mechanisms
115
- - Execution tracking and detailed logging
116
-
117
- #### Data Management
118
- - SQLite database with complete schema for all data entities
119
- - CRUD operations for executions, customers, lead scores, and email drafts
120
- - Data export/import functionality for backup and migration
121
- - Local data storage ensuring complete data ownership
122
-
123
- #### Configuration System
124
- - Team-specific configuration management
125
- - Customizable LLM prompts for all stages
126
- - Configurable scoring criteria and email templates
127
- - JSON-based configuration files with validation
128
-
129
- #### LLM Integration
130
- - OpenAI GPT-4o-mini client with error handling
131
- - Structured response parsing and validation
132
- - Token usage tracking and optimization
133
- - Response caching and retry mechanisms
134
-
135
- #### Documentation
136
- - Comprehensive README with installation and usage instructions
137
- - Technical documentation covering architecture and APIs
138
- - Business logic documentation extracted from original system
139
- - Troubleshooting guide and development workflow
140
-
141
- ### Technical Details
142
-
143
- #### Project Structure
144
- ```
145
- fusesell-local/
146
- fusesell.py # Main CLI entry point
147
- requirements.txt # Python dependencies
148
- setup.py # Package installation
149
- README.md # User documentation
150
- TECHNICAL.md # Technical documentation
151
- CHANGELOG.md # This file
152
- business_logic.md # Business logic documentation
153
- fusesell_local/ # Main package
154
- pipeline.py # Pipeline orchestrator
155
- stages/ # Pipeline stages (base implementation)
156
- utils/ # Utilities (data, LLM, validation, logging)
157
- config/ # Configuration management
158
- fusesell_data/ # Local data storage
159
- config/ # Configuration files
160
- drafts/ # Generated email drafts
161
- logs/ # Execution logs
162
- ```
163
-
164
- #### Key Features Implemented
165
- - **Local Execution**: Complete data ownership with no external dependencies except LLM API
166
- - **Business Logic Preservation**: All orchestration intelligence from original YAML workflows
167
- - **Flexible Data Sources**: Support for websites, business cards, social media, and manual input
168
- - **Stage Control**: Skip stages, stop after specific stages, save intermediate results
169
- - **Process Continuation**: Resume executions from any point with specific actions
170
- - **Comprehensive Validation**: Input validation, configuration validation, and error handling
171
- - **Extensible Architecture**: Modular design for easy customization and extension
172
-
173
- #### Database Schema
174
- - `executions`: Execution tracking and metadata
175
- - `stage_results`: Individual stage outputs and status
176
- - `customers`: Customer profiles and contact information
177
- - `lead_scores`: Scoring results and recommendations
178
- - `email_drafts`: Generated email content and variations
179
-
180
- #### Configuration Files
181
- - `prompts.json`: LLM prompts for all stages
182
- - `scoring_criteria.json`: Lead scoring rules and weights
183
- - `email_templates.json`: Email template variations
184
- - `team_settings.json`: Team-specific configurations
185
-
186
- ### Next Phase - Stage Implementations
187
-
188
- The core infrastructure is complete and ready for individual stage implementations:
189
-
190
- #### Planned Stage Development
191
- 1. **Data Acquisition**: Website scraping, business card OCR, social media extraction
192
- 2. **Data Preparation**: AI-powered data structuring and pain point identification
193
- 3. **Lead Scoring**: Product-customer fit evaluation with detailed breakdowns
194
- 4. **Initial Outreach**: Personalized email generation with multiple approaches
195
- 5. **Follow-up**: Context-aware follow-up sequences and timing optimization
196
-
197
- #### Development Status
198
- - Core infrastructure (CLI, pipeline, database, configuration)
199
- - Business logic validation and orchestration rules
200
- - Process continuation and human-in-the-loop controls
201
- - Comprehensive documentation and user guides
202
- - Individual stage implementations (next development phase)
203
-
204
- ### Migration from Server-Based System
205
-
206
- This release represents a complete conversion of the server-based FuseSell system to a local implementation:
207
-
208
- #### Preserved Features
209
- - All business logic and orchestration intelligence
210
- - Team-specific prompts and configuration
211
- - Human approval workflows and controls
212
- - Comprehensive logging and execution tracking
213
- - Multi-stage pipeline with flexible control
214
-
215
- #### Enhanced Features
216
- - Complete local data ownership and privacy
217
- - Command-line interface with extensive options
218
- - Process continuation and recovery capabilities
219
- - Flexible data source handling
220
- - Enhanced error handling and validation
221
-
222
- #### Architectural Improvements
223
- - Modular, extensible design
224
- - Comprehensive input validation
225
- - Local SQLite database for performance
226
- - Configuration-driven customization
227
- - Detailed technical documentation
228
-
229
- ### Installation and Usage
230
-
231
- #### Requirements
232
- - Python 3.8+
233
- - OpenAI API key
234
- - 50MB disk space for installation
235
- - Additional space for data storage (varies by usage)
236
-
237
- #### Quick Start
238
- ```bash
239
- # Install dependencies
240
- pip install -r requirements.txt
241
-
242
- # Run basic execution
243
- python fusesell.py --openai-api-key YOUR_API_KEY \
244
- --org-id your_org \
245
- --org-name "Your Company" \
246
- --customer-website "https://example.com"
247
- ```
248
-
249
- #### Advanced Usage
250
- ```bash
251
- # Full pipeline with custom settings
252
- python fusesell.py --openai-api-key sk-xxx \
253
- --org-id rta \
254
- --org-name "RTA Corp" \
255
- --customer-website "https://example.com" \
256
- --customer-name "Acme Inc" \
257
- --contact-name "John Doe" \
258
- --team-id sales_team_1 \
259
- --language english \
260
- --output-format json \
261
- --data-dir ./custom_data
262
- ```
263
-
264
- ### Support and Development
265
-
266
- For technical support, feature requests, or contributions:
267
- - Review the technical documentation in `TECHNICAL.md`
268
- - Check the troubleshooting guide for common issues
269
- - Refer to the business logic documentation for workflow details
270
- - Contact the development team for advanced customization needs
271
-
272
- ---
273
-
274
- ## Future Releases
275
-
276
- ### [1.1.0] - Planned
277
- - Complete data acquisition stage implementation
278
- - Website scraping with content extraction
279
- - Business card OCR processing
280
- - Social media profile data extraction
281
-
282
- ### [1.2.0] - Planned
283
- - Complete data preparation stage implementation
284
- - AI-powered customer profiling
285
- - Pain point identification and analysis
286
- - Financial and technology stack analysis
287
-
288
- ### [1.3.0] - Planned
289
- - Complete lead scoring stage implementation
290
- - Product-customer fit evaluation
291
- - Detailed scoring breakdowns and recommendations
292
- - Multi-product scoring capabilities
293
-
294
- ### [1.4.0] - Planned
295
- - Complete initial outreach stage implementation
296
- - Personalized email generation
297
- - Multiple draft variations and approaches
298
- - Human review workflow integration
299
-
300
- ### [1.5.0] - Planned
301
- - Complete follow-up stage implementation
302
- - Context-aware follow-up sequences
303
- - Interaction history analysis
85
+
86
+ ### Changed
87
+ - Distribution renamed to `fusesell` to align with upcoming PyPI publication; console entry point now resolves to `fusesell_local.cli:main`.
88
+ - CLI implementation moved into `fusesell_local/cli.py`, with top-level `fusesell.py` delegating for backward compatibility.
89
+ - Documentation refreshed to instruct `pip install fusesell` and demonstrate programmatic CLI reuse.
90
+ - Published version `1.2.0` to PyPI under the `fusesell` distribution name.
91
+
92
+ ### Fixed
93
+ - Ensured package metadata includes the CLI module so installations via pip expose the `fusesell` console script.
94
+
95
+ ## [1.1.0] - 2025-10-20
96
+
97
+ ### Added
98
+ - Library-first API (`fusesell_local.api`) exposing `build_config`, `execute_pipeline`, and supporting helpers for embedding FuseSell in external runtimes.
99
+ - Public exports in `fusesell_local.__init__` so consumers can import `FuseSellPipeline` and the new helpers directly.
100
+ - Programmatic configuration validation error (`ConfigValidationError`) for clearer failures in host applications.
101
+
102
+ ### Changed
103
+ - CLI now delegates configuration/build/validation/logging to the shared library utilities, ensuring consistent behaviour across CLI and embedded usage.
104
+ - Pipeline context now forwards scheduling preferences (timezone, send_immediately, business hour fields) from configuration to stages.
105
+
106
+ ### Fixed
107
+ - Continuation validation correctly requires `selected_draft_id` when performing `draft_rewrite` or `send` actions.
108
+
109
+ ## [1.0.0] - 2025-01-07
110
+
111
+ ### Added - Core Infrastructure Complete
112
+
113
+ #### CLI Interface
114
+ - Complete command-line interface with 25+ configuration options
115
+ - Comprehensive argument validation and error handling
116
+ - Multiple output formats (JSON, YAML, text)
117
+ - Dry-run mode for safe testing
118
+ - Process continuation support for resuming executions
119
+
120
+ #### Pipeline Engine
121
+ - Full pipeline orchestration with stage control
122
+ - Business logic validation extracted from original YAML workflows
123
+ - Sequential stage execution with data flow management
124
+ - Human-in-the-loop controls and approval points
125
+ - Comprehensive error handling and recovery mechanisms
126
+ - Execution tracking and detailed logging
127
+
128
+ #### Data Management
129
+ - SQLite database with complete schema for all data entities
130
+ - CRUD operations for executions, customers, lead scores, and email drafts
131
+ - Data export/import functionality for backup and migration
132
+ - Local data storage ensuring complete data ownership
133
+
134
+ #### Configuration System
135
+ - Team-specific configuration management
136
+ - Customizable LLM prompts for all stages
137
+ - Configurable scoring criteria and email templates
138
+ - JSON-based configuration files with validation
139
+
140
+ #### LLM Integration
141
+ - OpenAI GPT-4o-mini client with error handling
142
+ - Structured response parsing and validation
143
+ - Token usage tracking and optimization
144
+ - Response caching and retry mechanisms
145
+
146
+ #### Documentation
147
+ - Comprehensive README with installation and usage instructions
148
+ - Technical documentation covering architecture and APIs
149
+ - Business logic documentation extracted from original system
150
+ - Troubleshooting guide and development workflow
151
+
152
+ ### Technical Details
153
+
154
+ #### Project Structure
155
+ ```
156
+ fusesell-local/
157
+ fusesell.py # Main CLI entry point
158
+ requirements.txt # Python dependencies
159
+ setup.py # Package installation
160
+ README.md # User documentation
161
+ TECHNICAL.md # Technical documentation
162
+ CHANGELOG.md # This file
163
+ business_logic.md # Business logic documentation
164
+ fusesell_local/ # Main package
165
+ pipeline.py # Pipeline orchestrator
166
+ stages/ # Pipeline stages (base implementation)
167
+ utils/ # Utilities (data, LLM, validation, logging)
168
+ config/ # Configuration management
169
+ fusesell_data/ # Local data storage
170
+ config/ # Configuration files
171
+ drafts/ # Generated email drafts
172
+ logs/ # Execution logs
173
+ ```
174
+
175
+ #### Key Features Implemented
176
+ - **Local Execution**: Complete data ownership with no external dependencies except LLM API
177
+ - **Business Logic Preservation**: All orchestration intelligence from original YAML workflows
178
+ - **Flexible Data Sources**: Support for websites, business cards, social media, and manual input
179
+ - **Stage Control**: Skip stages, stop after specific stages, save intermediate results
180
+ - **Process Continuation**: Resume executions from any point with specific actions
181
+ - **Comprehensive Validation**: Input validation, configuration validation, and error handling
182
+ - **Extensible Architecture**: Modular design for easy customization and extension
183
+
184
+ #### Database Schema
185
+ - `executions`: Execution tracking and metadata
186
+ - `stage_results`: Individual stage outputs and status
187
+ - `customers`: Customer profiles and contact information
188
+ - `lead_scores`: Scoring results and recommendations
189
+ - `email_drafts`: Generated email content and variations
190
+
191
+ #### Configuration Files
192
+ - `prompts.json`: LLM prompts for all stages
193
+ - `scoring_criteria.json`: Lead scoring rules and weights
194
+ - `email_templates.json`: Email template variations
195
+ - `team_settings.json`: Team-specific configurations
196
+
197
+ ### Next Phase - Stage Implementations
198
+
199
+ The core infrastructure is complete and ready for individual stage implementations:
200
+
201
+ #### Planned Stage Development
202
+ 1. **Data Acquisition**: Website scraping, business card OCR, social media extraction
203
+ 2. **Data Preparation**: AI-powered data structuring and pain point identification
204
+ 3. **Lead Scoring**: Product-customer fit evaluation with detailed breakdowns
205
+ 4. **Initial Outreach**: Personalized email generation with multiple approaches
206
+ 5. **Follow-up**: Context-aware follow-up sequences and timing optimization
207
+
208
+ #### Development Status
209
+ - Core infrastructure (CLI, pipeline, database, configuration)
210
+ - Business logic validation and orchestration rules
211
+ - Process continuation and human-in-the-loop controls
212
+ - Comprehensive documentation and user guides
213
+ - Individual stage implementations (next development phase)
214
+
215
+ ### Migration from Server-Based System
216
+
217
+ This release represents a complete conversion of the server-based FuseSell system to a local implementation:
218
+
219
+ #### Preserved Features
220
+ - All business logic and orchestration intelligence
221
+ - Team-specific prompts and configuration
222
+ - Human approval workflows and controls
223
+ - Comprehensive logging and execution tracking
224
+ - Multi-stage pipeline with flexible control
225
+
226
+ #### Enhanced Features
227
+ - Complete local data ownership and privacy
228
+ - Command-line interface with extensive options
229
+ - Process continuation and recovery capabilities
230
+ - Flexible data source handling
231
+ - Enhanced error handling and validation
232
+
233
+ #### Architectural Improvements
234
+ - Modular, extensible design
235
+ - Comprehensive input validation
236
+ - Local SQLite database for performance
237
+ - Configuration-driven customization
238
+ - Detailed technical documentation
239
+
240
+ ### Installation and Usage
241
+
242
+ #### Requirements
243
+ - Python 3.8+
244
+ - OpenAI API key
245
+ - 50MB disk space for installation
246
+ - Additional space for data storage (varies by usage)
247
+
248
+ #### Quick Start
249
+ ```bash
250
+ # Install dependencies
251
+ pip install -r requirements.txt
252
+
253
+ # Run basic execution
254
+ python fusesell.py --openai-api-key YOUR_API_KEY \
255
+ --org-id your_org \
256
+ --org-name "Your Company" \
257
+ --customer-website "https://example.com"
258
+ ```
259
+
260
+ #### Advanced Usage
261
+ ```bash
262
+ # Full pipeline with custom settings
263
+ python fusesell.py --openai-api-key sk-xxx \
264
+ --org-id rta \
265
+ --org-name "RTA Corp" \
266
+ --customer-website "https://example.com" \
267
+ --customer-name "Acme Inc" \
268
+ --contact-name "John Doe" \
269
+ --team-id sales_team_1 \
270
+ --language english \
271
+ --output-format json \
272
+ --data-dir ./custom_data
273
+ ```
274
+
275
+ ### Support and Development
276
+
277
+ For technical support, feature requests, or contributions:
278
+ - Review the technical documentation in `TECHNICAL.md`
279
+ - Check the troubleshooting guide for common issues
280
+ - Refer to the business logic documentation for workflow details
281
+ - Contact the development team for advanced customization needs
282
+
283
+ ---
284
+
285
+ ## Future Releases
286
+
287
+ ### [1.1.0] - Planned
288
+ - Complete data acquisition stage implementation
289
+ - Website scraping with content extraction
290
+ - Business card OCR processing
291
+ - Social media profile data extraction
292
+
293
+ ### [1.2.0] - Planned
294
+ - Complete data preparation stage implementation
295
+ - AI-powered customer profiling
296
+ - Pain point identification and analysis
297
+ - Financial and technology stack analysis
298
+
299
+ ### [1.3.0] - Planned
300
+ - Complete lead scoring stage implementation
301
+ - Product-customer fit evaluation
302
+ - Detailed scoring breakdowns and recommendations
303
+ - Multi-product scoring capabilities
304
+
305
+ ### [1.4.0] - Planned
306
+ - Complete initial outreach stage implementation
307
+ - Personalized email generation
308
+ - Multiple draft variations and approaches
309
+ - Human review workflow integration
310
+
311
+ ### [1.5.0] - Planned
312
+ - Complete follow-up stage implementation
313
+ - Context-aware follow-up sequences
314
+ - Interaction history analysis
304
315
  - Automated timing optimization
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fusesell
3
- Version: 1.2.8
3
+ Version: 1.2.9
4
4
  Summary: Local implementation of FuseSell AI sales automation pipeline
5
5
  Author-email: FuseSell Team <team@fusesell.ai>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fusesell
3
- Version: 1.2.8
3
+ Version: 1.2.9
4
4
  Summary: Local implementation of FuseSell AI sales automation pipeline
5
5
  Author-email: FuseSell Team <team@fusesell.ai>
6
6
  License-Expression: MIT
@@ -32,6 +32,6 @@ __all__ = [
32
32
  "validate_config",
33
33
  ]
34
34
 
35
- __version__ = "1.2.8"
35
+ __version__ = "1.2.9"
36
36
  __author__ = "FuseSell Team"
37
37
  __description__ = "Local implementation of FuseSell AI sales automation pipeline"
@@ -904,6 +904,7 @@ class InitialOutreachStage(BaseStage):
904
904
  first_name = name_parts[0]
905
905
  else:
906
906
  first_name = contact_name or ''
907
+ context.setdefault('customer_first_name', first_name or contact_name or '')
907
908
 
908
909
  action = input_data.get('action', 'draft_write')
909
910
  action_labels = {
@@ -1044,7 +1045,7 @@ class InitialOutreachStage(BaseStage):
1044
1045
  return rep
1045
1046
  return reps[0] if reps else {}
1046
1047
 
1047
- def _sanitize_email_body(self, html: str, staff_name: str, rep_profile: Dict[str, Any]) -> str:
1048
+ def _sanitize_email_body(self, html: str, staff_name: str, rep_profile: Dict[str, Any], customer_first_name: str) -> str:
1048
1049
  if not html:
1049
1050
  return ''
1050
1051
 
@@ -1065,12 +1066,84 @@ class InitialOutreachStage(BaseStage):
1065
1066
  else:
1066
1067
  html = html.replace(placeholder, '')
1067
1068
 
1068
- # Remove any lingering placeholder fragments such as "[Your LinkedIn Profile"
1069
1069
  html = re.sub(r'\[Your[^<\]]+\]?', '', html, flags=re.IGNORECASE)
1070
- # Collapse empty paragraphs created by placeholder removal
1070
+
1071
+ if '<p' not in html.lower():
1072
+ lines = [line.strip() for line in html.splitlines() if line.strip()]
1073
+ if lines:
1074
+ html = ''.join(f'<p>{line}</p>' for line in lines)
1075
+
1076
+ html = self._deduplicate_greeting(html, customer_first_name or '')
1071
1077
  html = re.sub(r'(<p>\s*</p>)+', '', html, flags=re.IGNORECASE)
1072
1078
  return html
1073
1079
 
1080
+ def _deduplicate_greeting(self, html: str, customer_first_name: str) -> str:
1081
+ paragraphs = re.findall(r'(<p.*?>.*?</p>)', html, flags=re.IGNORECASE | re.DOTALL)
1082
+ if not paragraphs:
1083
+ return html
1084
+
1085
+ greeting_seen = False
1086
+ cleaned: List[str] = []
1087
+ for para in paragraphs:
1088
+ text = self._strip_html_tags(para).strip()
1089
+ normalized_para = para
1090
+ if self._looks_like_greeting(text):
1091
+ normalized_para = self._standardize_greeting_paragraph(para, customer_first_name)
1092
+ if greeting_seen:
1093
+ continue
1094
+ greeting_seen = True
1095
+ cleaned.append(normalized_para)
1096
+
1097
+ remainder = re.sub(r'(<p.*?>.*?</p>)', '__PARA__', html, flags=re.IGNORECASE | re.DOTALL)
1098
+ rebuilt = ''
1099
+ idx = 0
1100
+ for segment in remainder.split('__PARA__'):
1101
+ rebuilt += segment
1102
+ if idx < len(cleaned):
1103
+ rebuilt += cleaned[idx]
1104
+ idx += 1
1105
+ if idx < len(cleaned):
1106
+ rebuilt += ''.join(cleaned[idx:])
1107
+ return rebuilt
1108
+
1109
+ def _looks_like_greeting(self, text: str) -> bool:
1110
+ lowered = text.lower().replace('\xa0', ' ').strip()
1111
+ return lowered.startswith(('hi ', 'hello ', 'dear '))
1112
+
1113
+ def _standardize_greeting_paragraph(self, paragraph_html: str, customer_first_name: str) -> str:
1114
+ text = self._strip_html_tags(paragraph_html).strip()
1115
+ lowered = text.lower()
1116
+ first_word = next((candidate.title() for candidate in ('dear', 'hello', 'hi') if lowered.startswith(candidate)), 'Hi')
1117
+
1118
+ if customer_first_name:
1119
+ greeting = f"{first_word} {customer_first_name},"
1120
+ else:
1121
+ greeting = f"{first_word} there,"
1122
+
1123
+ remainder = ''
1124
+ match = re.match(r' *(hi|hello|dear)\b[^,]*,(.*)', text, flags=re.IGNORECASE | re.DOTALL)
1125
+ if match:
1126
+ remainder = match.group(2).lstrip()
1127
+ elif lowered.startswith(('hi', 'hello', 'dear')):
1128
+ parts = text.split(',', 1)
1129
+ if len(parts) > 1:
1130
+ remainder = parts[1].lstrip()
1131
+ else:
1132
+ remainder = text[len(text.split(' ', 1)[0]):].lstrip()
1133
+
1134
+ if remainder:
1135
+ sanitized_text = f"{greeting} {remainder}".strip()
1136
+ else:
1137
+ sanitized_text = greeting
1138
+
1139
+ return re.sub(
1140
+ r'(<p.*?>).*?(</p>)',
1141
+ lambda m: f"{m.group(1)}{sanitized_text}{m.group(2)}",
1142
+ paragraph_html,
1143
+ count=1,
1144
+ flags=re.IGNORECASE | re.DOTALL
1145
+ )
1146
+
1074
1147
  def _extract_first_name(self, full_name: str) -> str:
1075
1148
  if not full_name:
1076
1149
  return ''
@@ -1177,7 +1250,8 @@ class InitialOutreachStage(BaseStage):
1177
1250
  message_type = entry.get('message_type') or 'Email'
1178
1251
  rep_profile = getattr(self, '_active_rep_profile', {}) or {}
1179
1252
  staff_name = context.get('input_data', {}).get('staff_name') or self.config.get('staff_name', 'Sales Team')
1180
- email_body = self._sanitize_email_body(email_body, staff_name, rep_profile)
1253
+ first_name = context.get('customer_first_name') or context.get('input_data', {}).get('customer_name') or ''
1254
+ email_body = self._sanitize_email_body(email_body, staff_name, rep_profile, first_name)
1181
1255
 
1182
1256
  metadata = {
1183
1257
  'customer_company': customer_data.get('companyInfo', {}).get('name', 'Unknown'),
@@ -84,6 +84,7 @@ class EventScheduler:
84
84
  status TEXT NOT NULL,
85
85
  task TEXT NOT NULL,
86
86
  cron TEXT NOT NULL,
87
+ cron_ts INTEGER,
87
88
  room_id TEXT,
88
89
  tags TEXT,
89
90
  customextra TEXT,
@@ -115,6 +116,11 @@ class EventScheduler:
115
116
  CREATE INDEX IF NOT EXISTS idx_reminder_task_cron
116
117
  ON reminder_task(cron)
117
118
  """)
119
+
120
+ cursor.execute("PRAGMA table_info(reminder_task)")
121
+ columns = {row[1] for row in cursor.fetchall()}
122
+ if 'cron_ts' not in columns:
123
+ cursor.execute("ALTER TABLE reminder_task ADD COLUMN cron_ts INTEGER")
118
124
 
119
125
  conn.commit()
120
126
  conn.close()
@@ -191,6 +197,19 @@ class EventScheduler:
191
197
  except ValueError:
192
198
  return value_str
193
199
 
200
+ def _to_unix_timestamp(self, value: Union[str, datetime, None]) -> Optional[int]:
201
+ """
202
+ Convert a datetime-like value to a Unix timestamp (seconds).
203
+ """
204
+ iso_value = self._format_datetime(value)
205
+ try:
206
+ parsed = datetime.fromisoformat(iso_value)
207
+ except ValueError:
208
+ return None
209
+ if parsed.tzinfo is None:
210
+ parsed = parsed.replace(tzinfo=timezone.utc)
211
+ return int(parsed.timestamp())
212
+
194
213
  def _build_reminder_payload(
195
214
  self,
196
215
  base_context: Dict[str, Any],
@@ -296,11 +315,13 @@ class EventScheduler:
296
315
 
297
316
  cron_value = self._format_datetime(cron_value or send_time)
298
317
  scheduled_time_str = self._format_datetime(scheduled_time_value or send_time)
318
+ cron_ts = self._to_unix_timestamp(cron_value)
299
319
 
300
320
  return {
301
321
  'status': status,
302
322
  'task': task_label,
303
323
  'cron': cron_value,
324
+ 'cron_ts': cron_ts,
304
325
  'room_id': room_id,
305
326
  'tags': tags,
306
327
  'customextra': customextra,
@@ -346,15 +367,20 @@ class EventScheduler:
346
367
  conn = sqlite3.connect(self.main_db_path)
347
368
  cursor = conn.cursor()
348
369
 
370
+ cron_ts = payload.get('cron_ts')
371
+ if cron_ts is None:
372
+ cron_ts = self._to_unix_timestamp(payload.get('cron'))
373
+
349
374
  cursor.execute("""
350
375
  INSERT INTO reminder_task
351
- (id, status, task, cron, room_id, tags, customextra, org_id, customer_id, task_id, import_uuid, scheduled_time)
352
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
376
+ (id, status, task, cron, cron_ts, room_id, tags, customextra, org_id, customer_id, task_id, import_uuid, scheduled_time)
377
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
353
378
  """, (
354
379
  reminder_id,
355
380
  payload.get('status', 'published'),
356
381
  payload.get('task') or 'FuseSell Reminder',
357
382
  self._format_datetime(payload.get('cron')),
383
+ cron_ts,
358
384
  payload.get('room_id'),
359
385
  tags_str,
360
386
  customextra_str,
@@ -455,6 +481,7 @@ class EventScheduler:
455
481
  draft_id=draft_id,
456
482
  customer_timezone=customer_timezone
457
483
  )
484
+ reminder_payload.setdefault('cron_ts', self._to_unix_timestamp(reminder_payload.get('cron')))
458
485
  reminder_task_id = self._insert_reminder_task(reminder_payload)
459
486
 
460
487
  # Log the scheduling
@@ -585,6 +612,7 @@ class EventScheduler:
585
612
  draft_id=original_draft_id,
586
613
  customer_timezone=event_data['customer_timezone']
587
614
  )
615
+ reminder_payload.setdefault('cron_ts', self._to_unix_timestamp(reminder_payload.get('cron')))
588
616
  reminder_task_id = self._insert_reminder_task(reminder_payload)
589
617
 
590
618
  self.logger.info(f"Scheduled follow-up event {followup_event_id} for {follow_up_time}")
@@ -834,18 +862,18 @@ class EventScheduler:
834
862
 
835
863
  # Convert to list of dictionaries
836
864
  events = []
837
- for row in rows:
838
- event = dict(zip(columns, row))
839
- # Parse event_data JSON
840
- if event['event_data']:
841
- try:
842
- event['event_data'] = json.loads(event['event_data'])
843
- except json.JSONDecodeError:
844
- pass
845
- events.append(event)
846
-
847
- return events
848
-
865
+ for row in rows:
866
+ event = dict(zip(columns, row))
867
+ # Parse event_data JSON
868
+ if event['event_data']:
869
+ try:
870
+ event['event_data'] = json.loads(event['event_data'])
871
+ except json.JSONDecodeError:
872
+ pass
873
+ events.append(event)
874
+
875
+ return events
876
+
849
877
  except Exception as e:
850
878
  self.logger.error(f"Failed to get scheduled events: {str(e)}")
851
879
  return []
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fusesell"
7
- version = "1.2.8"
7
+ version = "1.2.9"
8
8
  description = "Local implementation of FuseSell AI sales automation pipeline"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes