     1→<?php
     2→/**
     3→ * MongoDB Database Helper Class
     4→ *
     5→ * Provides MongoDB connection management and common database operations
     6→ * for the Email Intelligence System. Works alongside MySQL in dual-write mode.
     7→ *
     8→ * CALLING MAP:
     9→ * - Called by: Database.php (dual-write mode)
    10→ * - Uses: config/config.php for credentials
    11→ *
    12→ * USAGE:
    13→ *   $mongo = MongoDatabase::getInstance();
    14→ *   $contacts = $mongo->findAll('contacts', ['type' => 'client']);
    15→ *   $mongo->insert('contacts', ['email' => 'test@test.com', 'name' => 'Test']);
    16→ *
    17→ * @package EmailIntelligence
    18→ */
    19→
    20→namespace EmailIntelligence;
    21→
    22→use MongoDB\Client;
    23→use MongoDB\Database as MongoDb;
    24→use MongoDB\Collection;
    25→use MongoDB\BSON\ObjectId;
    26→use MongoDB\BSON\UTCDateTime;
    27→use Exception;
    28→
    29→class MongoDatabase
    30→{
    31→    /**
    32→     * Singleton instance
    33→     * @var MongoDatabase|null
    34→     */
    35→    private static ?MongoDatabase $instance = null;
    36→
    37→    /**
    38→     * MongoDB client
    39→     * @var Client|null
    40→     */
    41→    private ?Client $client = null;
    42→
    43→    /**
    44→     * MongoDB database
    45→     * @var MongoDb|null
    46→     */
    47→    private ?MongoDb $db = null;
    48→
    49→    /**
    50→     * Whether MongoDB is available
    51→     * @var bool
    52→     */
    53→    private bool $available = false;
    54→
    55→    /**
    56→     * Table to collection mapping (for compatibility)
    57→     * MySQL tables map to MongoDB collections
    58→     */
    59→    private array $collectionMap = [
    60→        'contacts' => 'contacts',
    61→        'emails' => 'emails',
    62→        'email_analysis' => 'email_analysis',
    63→        'contact_profiles' => 'contact_profiles',
    64→        'quotes' => 'quotes',
    65→        'sync_status' => 'sync_status',
    66→        'email_filters' => 'email_filters',
    67→        'analysis_queue' => 'analysis_queue',
    68→        'activity_log' => 'activity_log',
    69→        'thread_analysis' => 'thread_analysis',
    70→        'thread_participants' => 'thread_participants',
    71→        'learned_behaviors' => 'learned_behaviors',
    72→        'api_logs' => 'api_logs',
    73→        'alerts' => 'alerts',
    74→        'gmail_accounts' => 'gmail_accounts',
    75→        'client_psychology' => 'client_psychology',
    76→        'churn_risk_indicators' => 'churn_risk_indicators',
    77→        'price_perception_history' => 'price_perception_history',
    78→        'business_opportunities' => 'business_opportunities',
    79→        'client_company_intel' => 'client_company_intel',
    80→        'churn_risk_history' => 'churn_risk_history',
    81→        // Business Ideas collections
    82→        'business_ideas_projects' => 'business_ideas_projects',
    83→        'business_research_tasks' => 'business_research_tasks',
    84→        'business_research_findings' => 'business_research_findings',
    85→        'business_scenarios' => 'business_scenarios',
    86→        'owner_status' => 'owner_status',
    87→        // Chrome Extension scraping collections
    88→        'extension_scrape_queue' => 'extension_scrape_queue',
    89→        'extension_scraped_data' => 'extension_scraped_data',
    90→    ];
    91→
    92→    /**
    93→     * Private constructor for singleton pattern
    94→     */
    95→    private function __construct()
    96→    {
    97→        $this->connect();
    98→    }
    99→
   100→    /**

Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


     1→<?php
     2→/**
     3→ * Gmail API Client
     4→ *
     5→ * Handles OAuth2 authentication and Gmail API interactions
     6→ * for fetching emails from Gmail accounts.
     7→ *
     8→ * MULTI-ACCOUNT SUPPORT:
     9→ * - Can be instantiated with a specific account ID or email
    10→ * - Falls back to primary account if none specified
    11→ * - Each account has its own token file
    12→ *
    13→ * CALLING MAP:
    14→ * - Called by: EmailSync.php (main consumer)
    15→ * - Called by: public/oauth_callback.php (OAuth flow)
    16→ * - Called by: cli/sync_emails.php
    17→ * - Uses: config/config.php for OAuth credentials
    18→ * - Uses: GmailAccount.php for multi-account management
    19→ * - Uses: config/gmail_token_*.json for stored tokens
    20→ *
    21→ * OAUTH FLOW:
    22→ * 1. User visits public/index.php -> clicks "Connect Gmail"
    23→ * 2. Redirected to Google OAuth consent screen (with account state)
    24→ * 3. Google redirects to public/oauth_callback.php with code
    25→ * 4. oauth_callback.php calls handleAuthCallback() to exchange code for token
    26→ * 5. Token stored in config/gmail_token_{email}.json
    27→ * 6. Subsequent calls use stored token, auto-refreshing when expired
    28→ *
    29→ * @package EmailIntelligence
    30→ */
    31→
    32→namespace EmailIntelligence;
    33→
    34→use Google\Client as GoogleClient;
    35→use Google\Service\Gmail;
    36→use Google\Service\Gmail\Message;
    37→use Exception;
    38→
    39→class GmailClient
    40→{
    41→    /**
    42→     * Google API Client instance
    43→     * @var GoogleClient
    44→     */
    45→    private GoogleClient $client;
    46→
    47→    /**
    48→     * Gmail Service instance
    49→     * @var Gmail|null
    50→     */
    51→    private ?Gmail $service = null;
    52→
    53→    /**
    54→     * Current account data
    55→     * @var array|null
    56→     */
    57→    private ?array $account = null;
    58→
    59→    /**
    60→     * Account ID (from gmail_accounts table)
    61→     * @var int|null
    62→     */
    63→    private ?int $accountId = null;
    64→
    65→    /**
    66→     * User's email address
    67→     * @var string
    68→     */
    69→    private string $userEmail;
    70→
    71→    /**
    72→     * Path to OAuth credentials JSON
    73→     * @var string
    74→     */
    75→    private string $credentialsPath;
    76→
    77→    /**
    78→     * Path to store OAuth token
    79→     * @var string
    80→     */

Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


260:        case 'status':
294:        case 'contacts':
328:        case 'contact':
355:        case 'threads':
389:        case 'thread':
468:        case 'thread_for_ai':
514:        case 'thread_participants':
593:        case 'logs':
613:        case 'learned_behaviors':
648:        case 'emails':
694:        case 'email':
739:        case 'quotes':
797:        case 'filters':
814:        case 'add_filter':
840:        case 'remove_filter':
864:        case 'sync':
911:        case 'analyze':
971:        case 'analyze_thread':
1010:        case 'analysis_status':
1079:        case 'analyze_contact':
1114:        case 'contact_profile':
1169:        case 'build_profile':
1189:        case 'semantic_search':
1221:        case 'find_patterns':
1246:        case 'index_vectors':
1289:        case 'vector_status':
1301:        case 'scan_patterns':
1320:        case 'detect_pattern':
1340:        case 'pattern_stats':
1355:        case 'similar_contacts':
1377:        case 'pricing_behavior':
1393:        case 'gmail_auth_url':
1412:        case 'gmail_accounts':
1428:        case 'gmail_account_add':
1466:        case 'gmail_account_remove':
1492:        case 'gmail_account_primary':
1514:        case 'gmail_account_toggle':
1539:        case 'update_quote':
1566:        case 'update_contact':
1600:        case 'alerts':
1629:        case 'alert_stats':
1639:        case 'scan_alerts':
1660:        case 'alert_read':
1677:        case 'alert_dismiss':
1694:        case 'analyze_batch':
1737:        case 'resolve_message_thread':
1843:        case 'sync_thread':
2107:        case 'save_gmail_thread':
2210:        case 'ask_ai':
2303:        case 'ai_chat':
2655:        case 'generate_reply':
2906:        case 'suggest_replies':
3072:        case 'client_insights':
3114:        case 'global_insights':
3149:        case 'insights_meta':
3167:        case 'ask_contact_ai':
3551:        case 'db_status':
3560:        case 'thread_id_cache':
3565:                case 'stats':
3572:                case 'lookup':
3585:                case 'list':
3592:                case 'clear_expired':
3608:        case 'quote_assistant':
3632:        case 'quote_stats':
3649:        case 'suggest_quote':
3671:        case 'extract_quotes':
3694:        case 'extraction_stats':
3709:        case 'list_quotes':
3754:        case 'projects':
3788:        case 'add_project':
3840:        case 'update_project':
3882:        case 'analyze_contact_full':
3927:        case 'analyze_contact_threads':
4030:        case 'stop_analysis':
4046:        case 'analysis_status':
4062:        case 'generate_email':
4389:        case 'count_filter_emails':
4439:        case 'enrich_contact':
4468:        case 'enrich_company':
4483:        case 'enrich_all_contacts':
4493:        case 'enrich_all_companies':
4503:        case 'suggest_enrichment_sources':
4527:        case 'approve_enrichment':
4555:        case 'enrichment_status':
4575:        case 'enrichment_queue':
4586:        case 'process_enrichment_queue':
4599:        case 'enrichment_logs':
4625:        case 'contact_enrichment':
4642:        case 'company_enrichment':
4659:        case 'apollo_status':
4670:        case 'puppeteer_status':
4681:        case 'enrichment_sources':
4693:        case 'save_important_context':
4716:        case 'get_important_context':
4729:        case 'delete_important_context':
4746:        case 'save_ai_response':
4800:        case 'log_ai_debug':
4839:        case 'get_ai_response':
4871:        case 'list_ai_responses':
4914:        case 'startProductSearch':
4948:        case 'getProductSearchStatus':
4965:        case 'getProductSearchResults':
4982:        case 'executeProductSearch':
5001:        case 'getProductSearchHistory':
5015:        case 'getProductSearchSites':
5030:        case 'saveProducts':
5084:        case 'business_ideas_projects':
5098:        case 'business_ideas_project':
5114:        case 'create_business_ideas_project':
5131:        case 'start_business_ideas_project':
5143:        case 'pause_business_ideas_project':
5155:        case 'resume_business_ideas_project':
5170:        case 'business_ideas_queue_status':
5178:        case 'process_business_ideas_queue':
5187:        case 'business_ideas_tasks':
5203:        case 'business_ideas_findings':
5218:        case 'business_ideas_scenarios':
5232:        case 'generate_business_ideas_report':
5244:        case 'generate_business_scenarios':
5261:        case 'business_context':
5268:        case 'get_owner_status':
5275:        case 'save_owner_status':
5294:        case 'web_search':
5320:        case 'web_search_urls':
5337:        case 'web_search_recent':
5356:        case 'web_search_status':
5364:        case 'extension_scrape_submit':
5412:        case 'extension_get_tasks':
5437:        case 'extension_queue_scrape':
5473:        case 'extension_complete_task':
5493:        case 'ai_chat_sessions':
5522:        case 'ai_chat_session':
5546:        case 'ai_chat_session_delete':
5559:        case 'ai_contact_memories':
5574:        case 'ai_contact_memory_add':
5601:        case 'ai_contact_memory_delete':

Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


325:    public function delete(string $collection, array $filter): int
326-    {
327-        if (!$this->available) {
328-            return 0;
329-        }
330-
331-        try {
332-            $coll = $this->getCollection($collection);
333-            $result = $coll->deleteMany($filter);
334-            return $result->getDeletedCount();
335-
336-        } catch (Exception $e) {
337-            $this->logError("MongoDB delete failed on {$collection}: " . $e->getMessage());
338-            return 0;
339-        }
340-    }

Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


4729:        case 'delete_important_context':
4730-            if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
4731-                jsonError('POST required', 405);
4732-            }
4733-
4734-            $id = $_POST['id'] ?? '';
4735-            if (!$id) jsonError('ID required');
4736-
4737-            $ctx = new ImportantContext();
4738-            $success = $ctx->delete($id);
4739-
4740-            jsonResponse(['success' => $success]);
4741-            break;
4742-
4743-        // ==========================================
4744-        // Save AI Query Response (MongoDB)
4745-        // ==========================================
4746-        case 'save_ai_response':
4747-            if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
4748-                jsonError('POST required', 405);
4749-            }

Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


482:    public function listMessages(string $query = '', int $maxResults = 100, ?string $pageToken = null): array
483-    {
484-        try {
485-            $service = $this->getService();
486-
487-            $params = [
--
577:    public function searchThreads(string $query, int $maxResults = 10): array
578-    {
579-        try {
580-            $service = $this->getService();
581-
582-            $params = [

Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


TodoWrite

Explore api.php action routing and existing delete/CRUD patterns

Exploring api.php action routing and patterns

Explore index.php UI (tabs, contacts list, threads list, navigation)

Explore app.js for AJAX calls and UI interaction patterns

Explore QueryAdapter.php MongoDB methods and getThreadsMongo

Explore thread_view.php for AI responses display

Explore GmailClient.php for search capabilities

Explore MongoDatabase.php for delete method signature

Explore aiapi/api_opus config for model versions

Design complete implementation plan

Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable

Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.


Prompt:
Design a detailed implementation plan for the following tasks in the Email Intelligence System at /var/www/mssql.danmarcrm.com/dev1/extension2v1/

## Context
This is a PHP/MongoDB web app with a dashboard (index.php + app.js), API (api.php), data layer (QueryAdapter.php), and a thread view page (thread_view.php). Chrome extension syncs Gmail threads. AI proxy at aiapi/api_opus/.

## Tasks (in priority order)

### TASK 1: Delete Functionality
Add ability to delete:
- **Contacts**: Already has a Delete button in dashboard UI. Need API endpoint `delete_contact` in api.php + QueryAdapter method. Must also delete associated emails, thread_analysis, contact_profiles, ai_contact_memory for that contact.
- **Email Threads**: Add delete button to threads list. API endpoint `delete_thread` + QueryAdapter. Must delete all emails with that thread_id, thread_analysis, ai_query_responses referencing that thread.
- **AI Responses**: Add delete button next to saved AI responses in thread_view.php. API endpoint `delete_ai_response`. Delete from ai_query_responses collection.

Files: api.php, QueryAdapter.php, app.js, index.php, thread_view.php

### TASK 2: Sorting by Last Activity
- Contacts list: Add sort by `last_contact` date (from contact profiles or max email date)
- Threads list: Add sort by `last_date` (already tracked in thread aggregation)
- Add sort dropdown/buttons in the UI for both tabs

Files: app.js, index.php, api.php (may need sort param support), QueryAdapter.php

### TASK 3: Filters
- **Contacts tab**: Add filters for contact type (client/supplier/other), search by name/email, last activity date range
- **Threads tab**: Add filters for contact name, date range, email count range, analysis status
- **Last Activity date filter**: Date range picker for both tabs
- Add filter UI section above each table

Files: app.js, index.php

### TASK 4: Fix "Etienne Turner" Thread Linkage
The contact name resolution was fixed in QueryAdapter.php but may still have issues:
- MongoDB `getThreadsMongo()` collects all_contacts, weights inbound 2x, picks most frequent
- But if contact_id is NULL or email matches user, it skips — edge case: if ALL emails in thread are from user (outbound only), falls back to first contact
- Need to verify the fix works and potentially handle edge cases

Files: QueryAdapter.php

### TASK 5: Sync by Domain/Email Address
New feature: Dashboard UI panel where user enters a domain (e.g. delta-engineering.be) or email address. System queries Gmail API to find all threads involving that domain/email, then imports them.

Implementation:
- New UI section in dashboard or modal
- New API endpoint `sync_by_domain` that:
  1. Uses GmailClient to search: `from:@domain.com OR to:@domain.com` (or specific email)
  2. Lists matching threads with preview (subject, date, count)
  3. User selects which to import (or "Import All")
  4. Imports selected threads using existing sync_thread logic
- Need two-step flow: search → preview → import

Files: api.php, index.php, app.js, GmailClient.php (may need search method)

### TASK 6: Bulk Delete Threads by Email Address
- Add ability to delete all threads for a specific email/domain
- UI: In contacts list or a cleanup tool
- API: `delete_threads_by_email` — finds all emails from that address, gets unique thread_ids, deletes all data

Files: api.php, QueryAdapter.php, app.js, index.php

### TASK 7: Chrome Extension Manual-Only Mode
- Add toggle in Chrome extension popup/options for "Auto-sync" vs "Manual sync only"
- In manual mode, show a "Sync this thread" button overlay in Gmail
- Store preference in chrome.storage.local
- Extension files are at /Users/dan/Documents/extension2/extension2v1/chrome-extension (local Mac) — we can only prepare the code changes

NOTE: Chrome extension is on user's local Mac, not this server. We should note what needs to change but can't edit those files directly.

### TASK 8: Two-Round AI D3.js Chart
- After Round 2 (or any AI response), add "Generate Chart" button
- AI generates structured JSON (entities, relationships, events)
- D3.js force-directed graph renders: nodes as balloons (color-coded by type), arrows showing relationships, labels
- Interactive: drag, zoom, pan, click for details

Files: thread_view.php (inline JS + D3.js CDN)

### TASK 9: Hide Products Tab
- Remove Products tab from navigation in index.php
- Keep product_search.php file intact

Files: index.php

### TASK 10: Update AI Model Versions
Update to latest models:
- Claude: Add `claude-opus-4-6`, `claude-sonnet-4-6` (current has claude-sonnet-4-5-20250929)
- Other providers: verify current versions

Files to update:
- /extension2v1/aiapi/api_opus/config/api_keys.php — provider models list + defaults
- /extension2v1/public/thread_view.php — MODEL_LIMITS constant
- /extension2v1/config/config.php — CLAUDE_MODEL constant
- Also check /extension2/aiapi/api_opus/config/api_keys.php

Current model config in api_keys.php uses arrays like:
```php
'claude' => [
    'default_model' => 'claude-sonnet-4-5-20250929',
    'models' => ['claude-sonnet-4-5-20250929', 'claude-3-5-sonnet-20241022', ...]
]
```

## Architecture Patterns to Follow
- Use `MongoDatabase::insertOrUpdate()` for upserts (NOT `upsert()`)
- Use `QueryAdapter` for all data access (NOT raw SQL)
- AI proxy models keyed by provider: `[$provider => $model]`
- MongoDB `delete()` method available on MongoDatabase class
- Node.js on server is v10.19 — can't use for JS syntax checks
- `ThreadAnalyzer::stripQuotedContent()` for email body processing

## Available MongoDB Methods (MongoDatabase.php)
- `insert($collection, $data)`
- `insertOrUpdate($collection, $filter, $data)`
- `update($collection, $filter, $data)`
- `delete($collection, $filter)`
- `findAll($collection, $filter, $options)`
- `findOne($collection, $filter)`
- `count($collection, $filter)`
- `aggregate($collection, $pipeline)`

## Existing API patterns
- JSON responses via `jsonResponse(['success' => true, ...])`
- Error handling via `jsonResponse(['success' => false, 'error' => '...'])`
- POST data via `$input = json_decode(file_get_contents('php://input'), true)`
- GET params via `$_GET['param']`

Please design a detailed, step-by-step plan with specific code changes needed for each task. Group related changes by file to minimize edits. Prioritize the tasks that are quickest wins first.