|
46366
|
979
|
0
|
2026-04-17T10:31:49.871934+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776421909871_m1.jpg...
|
PhpStorm
|
faVsco.js – ~/jiminny/app/front-end/src/components faVsco.js – ~/jiminny/app/front-end/src/components/connect/connect.vue...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Code changed:
Hide
Sync Changes
Hide This Notification
33
2
19
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use HubSpot\Client\Crm\Deals\Model\CollectionResponseAssociatedId;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\Account;
use Exception;
use Jiminny\Component\DealInsights\Forecast\Forecast;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Contact;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Exceptions\CrmException;
use Jiminny\Models\Opportunity;
use Illuminate\Support\Collection;
use Jiminny\Models\Stage;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Services\Crm\Hubspot\DealFieldsService;
use Jiminny\Services\Crm\Hubspot\OpportunitySyncStrategy\HubspotSingleSyncStrategy;
use Jiminny\Services\Crm\Hubspot\WebhookSyncBatchProcessor;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Utils\CurrencyFormatter;
/**
* Optimized sync methods for better performance
* These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains
*/
trait OpportunitySyncTrait
{
private const int BATCH_SIZE = 100;
private const int BATCH_PROCESS_SIZE = 800;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected DealFieldsService $dealFieldsService;
private ?array $cachedClosedDealStages = null;
private array $cachedBusinessProcesses = [];
private array $cachedStages = [];
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$parameters['config'] = $this->config;
$syncCount = 0;
$reportedTotal = 0;
$lastSyncedId = [];
try {
foreach ($strategies as $strategyName => $syncStrategy) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .
$strategyName
);
$total = 0;
$lastId = null;
$buffer = [];
// HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies
foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {
$buffer[] = $hsOpportunity;
// process every 800 rows (fits < 1 000 association limit)
if (\count($buffer) >= self::BATCH_PROCESS_SIZE) {
$syncCount += $this->processOpportunityBatch($buffer);
$buffer = [];
}
}
// leftovers
if ($buffer) {
$syncCount += $this->processOpportunityBatch($buffer);
}
$reportedTotal += $total;
$lastSyncedId = $lastId;
}
} catch (\HubSpot\Client\Crm\Deals\ApiException | CrmException $e) {
$this->handleSyncException($e, $parameters);
}
$this->logger->info(
'[HubSpot] Synced opportunities',
[
'team' => $this->team->getId(),
'sync_count' => $syncCount,
'total' => $reportedTotal,
'last_synced_id' => $lastSyncedId,
]
);
return $reportedTotal;
}
private function handleSyncException(\Throwable $e, array $parameters): void
{
if (($parameters['since'] ?? null) instanceof Carbon) {
$parameters['since'] = $parameters['since']->toDateTimeString();
}
$parameters['config'] = $this->config->getId();
$this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [
'teamId' => $this->team->getUuid(),
'parameters' => $parameters,
'reason' => $e->getMessage(),
]);
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,
);
$parameters = [
'config' => $this->config,
'crm_id' => $crmId,
];
try {
if (! $strategy instanceof HubspotSingleSyncStrategy) {
throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');
}
$hsOpportunity = $strategy->fetchOpportunity($parameters);
} catch (\HubSpot\Client\Crm\Deals\ApiException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->getUuid(),
'crmId' => $crmId,
'reason' => $e->getMessage(),
]);
return null;
}
$hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);
return $this->importOrUpdateOpportunity($hsOpportunity);
}
/**
* Process webhook-collected opportunity batches.
*
* Drains Redis sets containing company CRM IDs collected from webhook events
* and dispatches ImportOpportunityBatch jobs for batch processing.
*
* @return int Number of opportunity IDs dispatched to jobs
*/
public function batchSyncOpportunities(): int
{
$configId = $this->team->getCrmConfiguration()->getId();
return $this->batchProcessor->processBatchesForObjectType(
WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,
$configId
);
}
/**
* Import a batch of opportunities by their CRM IDs.
* Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().
*
* @param array<string> $crmIds HubSpot deal CRM IDs
*
* @return array{success: array, failed_ids: array, errors?: array<string, string>}
*/
public function importOpportunityBatchByIds(array $crmIds): array
{
$fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);
$allDeals = [];
foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {
$deals = $this->client->getOpportunitiesByIds($chunk, $fields);
foreach ($deals as $deal) {
$allDeals[] = $deal;
}
}
// IDs not returned by HubSpot are likely deleted or inaccessible deals.
// These are not failures — retrying won't bring them back.
$fetchedIds = array_map('strval', array_column($allDeals, 'id'));
$notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));
if (! empty($notFoundIds)) {
$this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [
'teamId' => $this->team->getId(),
'notFoundCount' => \count($notFoundIds),
'notFoundIds' => $notFoundIds,
'requestedCount' => \count($crmIds),
'fetchedCount' => \count($allDeals),
]);
}
if (empty($allDeals)) {
return ['success' => [], 'failed_ids' => []];
}
return $this->importOpportunityBatch($allDeals);
}
private function getClosedDealStages(): array
{
if ($this->cachedClosedDealStages !== null) {
return $this->cachedClosedDealStages;
}
$stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);
$data = [
'lost' => [],
'won' => [],
];
foreach ($stages as $stage) {
if ($stage->probability == 0.00) {
$data['lost'][] = $stage->crm_provider_id;
}
if ($stage->probability == 100.00) {
$data['won'][] = $stage->crm_provider_id;
}
}
$this->cachedClosedDealStages = $data;
return $data;
}
/**
* Import deals into the database with pre-fetched associations.
*
* API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT
* caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()
* where Laravel retries the whole job with backoff. After all retries exhausted,
* failed() requeues all IDs to Redis.
*
* The per-deal loop catches exceptions individually. A deal can end up in three states:
* - success: imported/updated successfully
* - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)
* These are permanent issues — retrying won't fix them.
* - skipped (null): missing dependencies (no account, unknown pipeline/stage).
* This is acceptable — the deal cannot be imported until those exist.
*/
private function importOpportunityBatch(array $deals): array
{
$syncedOpportunities = [
'success' => [],
'failed_ids' => [],
];
$dealIds = array_column($deals, 'id');
// Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the
// queue job retries the whole batch and eventually requeues all deal IDs back to Redis.
try {
$companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');
$contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');
$associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);
$existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(
$this->config,
array_map('strval', $dealIds)
);
$existingCrmIdSet = array_flip($existingCrmIds);
} catch (\Throwable $e) {
$this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [
'teamId' => $this->team->getId(),
'dealCount' => count($dealIds),
'error' => $e->getMessage(),
]);
throw $e;
}
foreach ($deals as $deal) {
try {
$deal['associations'] = $this->prepareAssociationsForOpportunity(
$deal['id'],
$companyAssociations,
$contactAssociations,
$associationsData
);
$syncedOpportunity = $this->importOrUpdateOpportunity(
$deal,
isset($existingCrmIdSet[(string) $deal['id']])
);
if ($syncedOpportunity) {
$syncedOpportunities['success'][] = $syncedOpportunity;
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [
'teamId' => $this->team->getId(),
'crmId' => $deal['id'],
'error' => $e->getMessage(),
]);
$syncedOpportunities['failed_ids'][] = $deal['id'];
$syncedOpportunities['errors'][$deal['id']] = $e->getMessage();
}
}
return $syncedOpportunities;
}
/**
* Prepare associated entities for opportunities with optimized batch processing
* Returns structured data with CRM ID to DB ID mappings for each opportunity
*/
private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array
{
// Step 1: Collect all unique company and contact IDs from associations
$allCompanyIds = $this->flattenAssociationIds($companyAssociations);
$allContactIds = $this->flattenAssociationIds($contactAssociations);
// Step 2: Batch sync missing entities and get CRM ID to DB ID mappings
$companyIdMappings = [];
$contactIdMappings = [];
if (! empty($allCompanyIds)) {
$companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);
}
if (! empty($allContactIds)) {
$contactIdMappings = $this->prepareAssociatedContacts($allContactIds);
}
return [
'company_id_mappings' => $companyIdMappings,
'contact_id_mappings' => $contactIdMappings,
];
}
/**
* Flatten association data to get unique IDs
*/
private function flattenAssociationIds(array $associations): array
{
$ids = [];
foreach ($associations as $dealAssociations) {
if (is_array($dealAssociations)) {
foreach ($dealAssociations as $id) {
$ids[$id] = true;
}
}
}
return array_keys($ids);
}
/**
* Batch sync missing accounts
*/
private function prepareAssociatedAccounts(array $companyIds): array
{
// Find which accounts already exist
$existingAccounts = $this->crmEntityRepository
->findAccountsByExternalIds($this->config, $companyIds);
$existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();
$existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {
return [$account->getCrmProviderId() => $account->getId()];
})->toArray();
$missingCompanyIds = array_diff($companyIds, $existingCompanyIds);
if (empty($missingCompanyIds)) {
return $existingAccountsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [
'teamId' => $this->team->getUuid(),
'total_companies' => count($companyIds),
'existing_companies' => count($existingCompanyIds),
'missing_companies' => count($missingCompanyIds),
]);
// we already have limit on opportunity ids count
// Initialize variable before try block
$syncedAccountsData = [];
try {
$syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [
'size' => count($missingCompanyIds),
'error' => $e->getMessage(),
]);
$syncedAccountsData = [];
}
return $existingAccountsData + $syncedAccountsData;
}
/**
* Prepare associated contacts - find existing and sync missing ones
* Returns mapping of CRM ID to DB ID
*/
private function prepareAssociatedContacts(array $contactIds): array
{
// Find which contacts already exist
$existingContacts = $this->crmEntityRepository
->findContactsByExternalIds($this->config, $contactIds);
$existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();
// Create mapping for existing contacts
$existingContactsData = $existingContacts->mapWithKeys(function ($contact) {
return [$contact->getCrmProviderId() => $contact->getId()];
})->toArray();
$missingContactIds = array_diff($contactIds, $existingContactIds);
if (empty($missingContactIds)) {
return $existingContactsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [
'teamId' => $this->team->getUuid(),
'total_contacts' => count($contactIds),
'existing_contacts' => count($existingContactIds),
'missing_contacts' => count($missingContactIds),
]);
// Sync missing contacts using batch API
try {
$syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [
'size' => count($missingContactIds),
'error' => $e->getMessage(),
]);
$syncedContactsData = [];
}
return $existingContactsData + $syncedContactsData;
}
private function batchSyncCrmObjects(string $objectType, array $crmIds): array
{
$syncObjects = [];
$crmObjectIds = array_values($crmIds);
foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {
try {
$objects = $objectType === 'companies' ?
$this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :
$this->client->getContactsByIds($chunk, $this->getContactFields());
foreach ($objects as $objectId => $objectData) {
$this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [
'requested_count' => count($chunk),
'synced_count' => count($objects),
]);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [
'ids' => $chunk,
'error' => $e->getMessage(),
]);
}
}
return $syncObjects;
}
private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void
{
try {
$object = $objectType === 'companies' ?
$this->importAccount($objectData) :
$this->importContact($objectData);
if ($object) {
$syncObjects[$object->getCrmProviderId()] = $object->getId();
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [
'id' => $objectId,
'error' => $e->getMessage(),
]);
}
}
/**
* Prepare associations for a single opportunity
*
* The return value is an array with the following structure:
* [
* 'companies' => [
* $companyCrmId => $companyId,
* ...
* ],
* 'contacts' => [
* $contactCrmId => $contactId,
* ...
* ],
* 'account_id' => $accountId,
* ]
*/
private function prepareAssociationsForOpportunity(
string $oppCrmId,
array $companyAssociations,
array $contactAssociations,
array $associationsData
): array {
$associations = [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
$oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];
foreach ($oppCompanyIds as $companyCrmId) {
if (isset($associationsData['company_id_mappings'][$companyCrmId])) {
$associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];
// Set primary account (first company becomes primary account)
if ($associations['account_id'] === null) {
$associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];
}
}
}
$oppContactIds = $contactAssociations[$oppCrmId] ?? [];
foreach ($oppContactIds as $contactCrmId) {
if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {
$associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];
}
}
return $associations;
}
/**
* Update only associations for an opportunity
*/
private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void
{
// Update contact associations
$this->importOpportunityContacts($opportunity, $associations['contacts']);
// Update company (account) associations
$this->updateOpportunityAccount($opportunity, $associations['account_id']);
}
/**
* Remove all contact associations from an opportunity
*/
private function removeAllOpportunityContacts(Opportunity $opportunity): void
{
$currentCount = (int) $opportunity->contacts()->count();
if ($currentCount > 0) {
$opportunity->contacts()->detach();
$this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_count' => $currentCount,
]);
}
}
private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void
{
if ($accountId === null) {
// No account ID provided - keep current account
return;
}
$currentAccountId = $opportunity->getAccountId();
// Only update if account has changed
if ($currentAccountId !== $accountId) {
$opportunity->account_id = $accountId;
$opportunity->save();
$this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [
'opportunity_id' => $opportunity->getId(),
'old_account_id' => $currentAccountId,
'new_account_id' => $accountId,
]);
}
}
/**
* Find existing opportunities by external IDs (OPTIMIZED VERSION)
* Uses batch query for better performance
*/
private function findExistingOpportunities(array $crmIds): Collection
{
return $this->crmEntityRepository
->findOpportunitiesByExternalIds($this->config, $crmIds);
}
private function processOpportunityBatch(array $opportunities): int
{
$syncedOpportunities = $this->importOpportunityBatch($opportunities);
return count($syncedOpportunities['success'] ?? []);
}
/**
* Convert single deal associations from HubSpot format to internal format
* Handles both HubSpot SDK objects and array formats
*
* @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed
*
* @return array Processed associations with DB IDs
*/
private function convertDealAssociations(array $opportunityAssociations): array
{
$associations = $this->initializeAssociationsStructure();
if (empty($opportunityAssociations)) {
return $associations;
}
$associationIds = $this->extractAssociationIds($opportunityAssociations);
$this->processCompanyAssociations($associationIds, $associations);
$this->processContactAssociations($associationIds, $associations);
return $associations;
}
private function initializeAssociationsStructure(): array
{
return [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
}
private function extractAssociationIds(array $opportunityAssociations): array
{
$associationIds = [];
foreach ($opportunityAssociations as $type => $associationData) {
if (! empty($associationData)) {
$associationIds[$type] = $this->convertSingleDealAssociations($associationData);
}
}
return $associationIds;
}
private function processCompanyAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['companies'])) {
return;
}
$companyId = $associationIds['companies'][0];
$account = $this->findOrSyncAccount($companyId);
if ($account instanceof Account) {
$associations['companies'][$companyId] = $account->getId();
$associations['account_id'] = $account->getId();
}
}
private function processContactAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['contacts'])) {
return;
}
foreach ($associationIds['contacts'] as $contactId) {
$contact = $this->findOrSyncContact($contactId);
if ($contact instanceof Contact) {
$associations['contacts'][$contactId] = $contact->getId();
}
}
}
private function findOrSyncAccount(string $companyId): ?Account
{
$account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);
if (! $account instanceof Account) {
$account = $this->syncAccount($companyId);
}
return $account;
}
private function findOrSyncContact(string $contactId): ?Contact
{
$contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);
if (! $contact instanceof Contact) {
$contact = $this->syncContact($contactId);
}
return $contact;
}
private function convertSingleDealAssociations($opportunityAssociations = null): array
{
$associationData = [];
if ($opportunityAssociations === null) {
return $associationData;
}
// Handle array input (from extractAssociationIds)
if (is_array($opportunityAssociations)) {
return $opportunityAssociations;
}
// Handle CollectionResponseAssociatedId object
if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {
foreach ($opportunityAssociations->getResults() as $association) {
$associationData[] = $association->getId();
}
}
return $associationData;
}
private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity
{
if (empty($crmData['properties'])) {
return null;
}
$crmId = (string) $crmData['id'];
$properties = $crmData['properties'];
$associations = $crmData['associations'] ?? [];
$opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(
$this->config,
$crmId
);
if ($opportunityExists) {
return $this->updateOpportunity($crmId, $properties, $associations);
} else {
return $this->createOpportunity($crmId, $properties, $associations);
}
}
/**
* Create new opportunity
*/
private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity
{
$accountId = $this->resolveAccountId($associations);
if (! $accountId) {
return null;
}
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
if (! $businessProcess) {
return null;
}
$stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);
if (! $stage) {
return null;
}
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->importOpportunityContacts($opportunity, $associations['contacts']);
if ($opportunity->wasRecentlyCreated) {
MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());
}
return $opportunity;
}
/**
* Update existing opportunity
*/
private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity
{
$accountId = $this->resolveAccountId($associations);
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
$stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->updateOpportunityAssociations($opportunity, $associations);
return $opportunity;
}
private function resolveAccountId(array $associations): ?int
{
if (! empty($associations['accountId'])) {
return $associations['accountId'];
}
if (empty($associations)) {
return null;
}
// we can't resolve multiple account ids (currently SDK returns one company)
foreach ($associations['companies'] as $accountId) {
return $accountId;
}
return null;
}
private function buildOpportunityData(
array $properties,
?int $accountId,
?BusinessProcess $businessProcess,
?Stage $stage
): array {
$ownerId = null;
$profile = null;
if (! empty($properties['hubspot_owner_id'])) {
$ownerId = $properties['hubspot_owner_id'];
$profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);
}
$name = 'Unknown';
if (isset($properties['dealname'])) {
$name = mb_strimwidth($properties['dealname'], 0, 128);
}
$amount = $this->resolveAmount($properties);
$currency = $properties['deal_currency_code'] ?? null;
$closeDate = null;
if (! empty($properties['closedate'])) {
$closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');
}
$remotelyCreatedAt = null;
if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {
$date = $this->parseCleanDatetime($properties['createdate']);
$remotelyCreatedAt = $date?->format('Y-m-d H:i:s');
}
$closedStages = $this->getClosedDealStages();
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$data = [
'team_id' => $this->team->getId(),
'user_id' => $profile ? $profile->user_id : null,
'owner_id' => $ownerId,
'name' => $name,
'value' => ! empty($amount) ? $amount : null,
'currency_code' => CurrencyFormatter::formatCode($currency),
'close_date' => $closeDate,
'is_closed' => $isWon || $isLost,
'is_won' => $isWon,
'remotely_created_at' => $remotelyCreatedAt,
'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),
'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),
];
if ($accountId) {
$data['account_id'] = $accountId;
}
if ($stage) {
$data['stage_id'] = $stage->id;
}
if ($businessProcess) {
$recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);
if ($recordType) {
$data['record_type_id'] = $recordType->id;
}
}
return $data;
}
private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess
{
if ($pipelineId === null) {
return null;
}
if (isset($this->cachedBusinessProcesses[$pipelineId])) {
return $this->cachedBusinessProcesses[$pipelineId];
}
$businessProcess = $this->getBusinessProcess($pipelineId);
if (! $businessProcess instanceof BusinessProcess) {
$this->importStages();
$businessProcess = $this->getBusinessProcess($pipelineId);
}
if (! $businessProcess instanceof BusinessProcess) {
$this->logger->info(
'[HubSpot] Deal is not attached to a pipeline',
[
'pipeline' => $pipelineId]
);
}
$this->cachedBusinessProcesses[$pipelineId] = $businessProcess;
return $businessProcess;
}
private function getBusinessProcess(string $pipelineId): ?BusinessProcess
{
return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);
}
private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage
{
if (empty($stageId)) {
return null;
}
$cacheKey = $businessProcess->getId() . ':' . $stageId;
if (isset($this->cachedStages[$cacheKey])) {
return $this->cachedStages[$cacheKey];
}
$stage = $this->crmEntityRepository->getPipelineStageByConditions(
$businessProcess,
[
'crm_provider_id' => $stageId,
'type' => Stage::TYPE_OPPORTUNITY,
]
);
if ($stage === null) {
$this->importStages(null, $stageId);
}
if ($stage === null) {
$this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);
}
$this->cachedStages[$cacheKey] = $stage;
return $stage;
}
private function resolveAmount(array $properties): ?string
{
$amount = null;
if (! empty($properties['amount'])) {
$amount = str_replace(',', '', $properties['amount']);
}
if ($this->config->hasDefaultCurrencyFieldSet()) {
$valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();
$amount = $properties[$valueFieldName] ?? $amount;
}
return $amount;
}
private function parseCleanDatetime(string $datetime): ?Carbon
{
// Treat pre-1980 values as invalid
$minValidDate = Carbon::parse('1980-01-01 00:00:00');
try {
$date = Carbon::parse($datetime);
if ($minValidDate->gt($date)) {
return null;
}
return $date;
} catch (Exception) {
return null; // On parse error, treat as null
}
}
private function resolveDealProbability(?string $stageProbability): int
{
if ($stageProbability === null) {
return 0;
}
$probability = (float) $stageProbability;
return $probability > 1 ? 0 : (int) ($probability * 100);
}
private function resolveForecastCategory(?string $forecastCategory): string
{
if (! $forecastCategory) {
return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;
}
$forecastCategory = str_replace('_', ' ', $forecastCategory);
return ucwords(strtolower($forecastCategory));
}
private function importExternalFieldData(array $properties, int $opportunityId): void
{
$crmFields = $this->getOpportunitySyncableFields();
$this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);
}
private function importOpportunityContacts(Opportunity $opportunity, array $associations): void
{
// Handle empty or missing contact associations
if (empty($associations)) {
// Remove all existing contact associations if none provided
$this->removeAllOpportunityContacts($opportunity);
return;
}
// Use differential sync approach for better performance and accuracy
$this->syncOpportunityContactsDifferential($opportunity, $associations);
}
/**
* Sync opportunity contacts using differential approach
* This compares current vs new associations and only makes necessary changes
*/
private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void
{
$currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);
$contactAssociationIds = array_keys($contactAssociations);
$contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);
$contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);
if (empty($contactsToAdd) && empty($contactsToRemove)) {
return;
}
$this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);
$this->removeContactAssociations($opportunity, $contactsToRemove);
$this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);
}
private function getCurrentContactCrmIds(Opportunity $opportunity): array
{
return $opportunity->contacts()
->pluck('contacts.crm_provider_id')
->toArray();
}
private function logContactAssociationChanges(
Opportunity $opportunity,
array $currentContactCrmIds,
array $contactAssociations,
array $contactsToAdd,
array $contactsToRemove
): void {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [
'opportunity_id' => $opportunity->getId(),
'current_contacts' => $currentContactCrmIds,
'new_contacts' => $contactAssociations,
'contacts_to_add' => $contactsToAdd,
'contacts_to_remove' => $contactsToRemove,
]);
}
private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void
{
if (empty($contactsToRemove)) {
return;
}
$contactsToDetach = $opportunity->contacts()
->whereIn('contacts.crm_provider_id', $contactsToRemove)
->pluck('contacts.id')
->toArray();
if (! empty($contactsToDetach)) {
$opportunity->contacts()->detach($contactsToDetach);
$this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_contact_crm_ids' => $contactsToRemove,
'removed_contact_count' => count($contactsToDetach),
]);
}
}
private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void
{
if (empty($contactsToAdd)) {
return;
}
$contactsAdded = [];
foreach ($contactsToAdd as $crmId) {
$id = $contactAssociations[$crmId];
if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {
$contactsAdded[] = $crmId;
}
}
$this->logAddedContacts($opportunity, $contactsAdded);
}
private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool
{
try {
$contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);
if (! $contact) {
return false;
}
return $this->performContactAttachment($opportunity, $contact, $crmId);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [
'opportunity_id' => $opportunity->getId(),
'contact_crm_id' => $crmId,
'error' => $e->getMessage(),
]);
return false;
}
}
private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool
{
try {
$opportunity->contacts()->attach($contact->getId(), [
'crm_provider_id' => $crmId,
]);
return true;
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [
'contact_id' => $contact->getId(),
'contact_crm_id' => $crmId,
'opportunity_id' => $opportunity->getId(),
]);
return false;
}
throw $e;
}
}
private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void
{
if (! empty($contactsAdded)) {
$this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [
'opportunity_id' => $opportunity->getId(),
'contacts_to_add_count' => count($contactsAdded),
'added_contact_crm_ids' => $contactsAdded,
'added_contacts_count' => count($contactsAdded),
]);
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<template>
<WelcomeLayout
title="Account disconnected"
textPosition="center"
:icon="faUnlink"
:class="$style.layout"
>
<div :class="$style.container" v-if="providersLoaded">
<p>
<strong>
It looks like your {{ localProvider.displayName }} account has become
disconnected
</strong>
</p>
<p :class="$style.small">Please re-connect to continue</p>
<p v-if="isInIframe">
We'll open the {{ localProvider.displayName }} authentication in a new
tab. Please return here and refresh the page once complete
</p>
<GoogleLikeButton
v-if="localProvider.viaIntegrationApp && crmTokenLoaded"
as="a"
:key="localProvider.name"
:brand-logo="localProvider.name"
:class="$style.connectButton"
@click="integrationAppOnClick"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
<GoogleLikeButton
v-if="!localProvider.viaIntegrationApp"
as="a"
:key="localProvider.name"
:href="`/auth/redirect/${localProvider.name}`"
:target="target"
:brand-logo="localProvider.name"
:class="$style.connectButton"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
</div>
<BuildInfo />
<KioskBanner />
</WelcomeLayout>
</template>
<script>
import window from "window";
import axios from "axios";
import { faUnlink } from "@fortawesome/pro-regular-svg-icons";
import isInIframe from "@/utils/isInIframe";
import BuildInfo from "@/components/layout/BuildInfo/BuildInfo.vue";
import KioskBanner from "@/components/shared/KioskBanner/KioskBanner.vue";
import WelcomeLayout from "@/components/layout/WelcomeLayout/WelcomeLayout.vue";
import GoogleLikeButton from "@/components/shared/Buttons/GoogleLikeButton.vue";
import { showSnackbarError, normalizeError } from "@/utils/index";
import { IntegrationAppClient } from "@integration-app/sdk";
export default {
name: "ConnectPage",
components: {
BuildInfo,
KioskBanner,
WelcomeLayout,
GoogleLikeButton,
},
data() {
return {
...window.connectData,
crmToken: null,
faUnlink,
isInIframe,
providers: [],
providersLoaded: false,
crmTokenLoaded: false,
};
},
computed: {
localProvider() {
return this.providers.find((e) => e.name === this.provider);
},
target() {
return this.isInIframe ? "_blank" : null;
},
},
created() {
this.getProviders();
},
mounted() {
this.showErrors();
},
watch: {
providersLoaded() {
if (this.providersLoaded) {
this.prepareIntegrationAppConnection();
}
},
},
methods: {
showErrors() {
if (!this.error) return;
showSnackbarError(this.error, undefined, undefined, false);
},
unwrapEntityResponse({ data }) {
return data.map(({ icon, name, displayName, viaIntegrationApp }) => {
return { icon, name, displayName, viaIntegrationApp };
});
},
async getProviders() {
try {
const response = await axios.get("/api/v1/connect-providers");
this.providers = this.unwrapEntityResponse(response);
this.providersLoaded = true;
} catch {
showSnackbarError(
"An error occurred, while loading form data (connect providers).",
);
}
},
async prepareIntegrationAppConnection() {
if (this.localProvider.viaIntegrationApp) {
try {
const response = await axios.get("/api/v1/integration-app-token");
this.crmToken = response.data.token;
this.crmTokenLoaded = true;
} catch (error) {
console.log(error);
showSnackbarError(
`An error occurred while preparing the page.
Try refreshing, if the error persists get in touch with the Jiminny team.`,
);
}
}
},
async integrationAppOnClick() {
const integrationApp = new IntegrationAppClient({
token: this.crmToken,
});
const connection = await integrationApp
.integration(this.localProvider.name)
.openNewConnection({
showPoweredBy: false,
allowMultipleConnections: false,
});
console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));
// [IntegrationApp] openNewConnection resolved: {
// "id":"69e0b41a67d0068c2ca0b48e",
// "name":"Zoho CRM",
// "userId":"1ece66c8-feb1-4df1-b321-21607daf4623",
// "tenantId":"69e0b3faef3e7b6248189289",
// "isTest":false,
// "connected":true,
// "state":"READY",
// "errors":[],
// "integrationId":"66fe6c913202f3a165e3c14d",
// "externalAppId":"6671653e7e2d642e4e41b0fa",
// "authOptionKey":"",
// "createdAt":"2026-04-16T10:04:10.420Z",
// "updatedAt":"2026-04-16T10:04:10.575Z",
// "retryAttempts":0,
// "isDeactivated":false
// }
if (connection && connection.disconnected !== true && connection.connected !== false) {
console.log('[IntegrationApp] connection condition matched');
try {
const saveRequest = await axios.post(
"/api/v1/integration-app-connect",
);
if (saveRequest.data && saveRequest.data.success === true) {
/** If all is good refresh the page here */
window.location = "/dashboard";
return;
}
throw new Error(saveRequest.data.message);
} catch (error) {
console.log(error);
showSnackbarError(normalizeError(error));
}
}
},
},
};
</script>
<style module lang="less" src="./connect.less"></style>
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2/4","depth":4,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"33","depth":4,"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\CollectionResponseAssociatedId;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\Account;\nuse Exception;\nuse Jiminny\\Component\\DealInsights\\Forecast\\Forecast;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Models\\Opportunity;\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Repositories\\Crm\\CrmEntityRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DealFieldsService;\nuse Jiminny\\Services\\Crm\\Hubspot\\OpportunitySyncStrategy\\HubspotSingleSyncStrategy;\nuse Jiminny\\Services\\Crm\\Hubspot\\WebhookSyncBatchProcessor;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Utils\\CurrencyFormatter;\n\n/**\n * Optimized sync methods for better performance\n * These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains\n */\ntrait OpportunitySyncTrait\n{\n private const int BATCH_SIZE = 100;\n private const int BATCH_PROCESS_SIZE = 800;\n\n protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n protected CrmEntityRepository $crmEntityRepository;\n protected DealFieldsService $dealFieldsService;\n\n private ?array $cachedClosedDealStages = null;\n private array $cachedBusinessProcesses = [];\n private array $cachedStages = [];\n\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n $parameters['config'] = $this->config;\n $syncCount = 0;\n $reportedTotal = 0;\n $lastSyncedId = [];\n\n try {\n foreach ($strategies as $strategyName => $syncStrategy) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .\n $strategyName\n );\n\n $total = 0;\n $lastId = null;\n $buffer = [];\n\n // HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies\n foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {\n $buffer[] = $hsOpportunity;\n\n // process every 800 rows (fits < 1 000 association limit)\n if (\\count($buffer) >= self::BATCH_PROCESS_SIZE) {\n $syncCount += $this->processOpportunityBatch($buffer);\n $buffer = [];\n }\n }\n\n // leftovers\n if ($buffer) {\n $syncCount += $this->processOpportunityBatch($buffer);\n }\n\n $reportedTotal += $total;\n $lastSyncedId = $lastId;\n }\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException | CrmException $e) {\n $this->handleSyncException($e, $parameters);\n }\n\n $this->logger->info(\n '[HubSpot] Synced opportunities',\n [\n 'team' => $this->team->getId(),\n 'sync_count' => $syncCount,\n 'total' => $reportedTotal,\n 'last_synced_id' => $lastSyncedId,\n ]\n );\n\n return $reportedTotal;\n }\n\n private function handleSyncException(\\Throwable $e, array $parameters): void\n {\n if (($parameters['since'] ?? null) instanceof Carbon) {\n $parameters['since'] = $parameters['since']->toDateTimeString();\n }\n $parameters['config'] = $this->config->getId();\n\n $this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [\n 'teamId' => $this->team->getUuid(),\n 'parameters' => $parameters,\n 'reason' => $e->getMessage(),\n ]);\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,\n );\n\n $parameters = [\n 'config' => $this->config,\n 'crm_id' => $crmId,\n ];\n\n try {\n if (! $strategy instanceof HubspotSingleSyncStrategy) {\n throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');\n }\n\n $hsOpportunity = $strategy->fetchOpportunity($parameters);\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->getUuid(),\n 'crmId' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);\n\n return $this->importOrUpdateOpportunity($hsOpportunity);\n }\n\n /**\n * Process webhook-collected opportunity batches.\n *\n * Drains Redis sets containing company CRM IDs collected from webhook events\n * and dispatches ImportOpportunityBatch jobs for batch processing.\n *\n * @return int Number of opportunity IDs dispatched to jobs\n */\n public function batchSyncOpportunities(): int\n {\n $configId = $this->team->getCrmConfiguration()->getId();\n\n return $this->batchProcessor->processBatchesForObjectType(\n WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,\n $configId\n );\n }\n\n /**\n * Import a batch of opportunities by their CRM IDs.\n * Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().\n *\n * @param array<string> $crmIds HubSpot deal CRM IDs\n *\n * @return array{success: array, failed_ids: array, errors?: array<string, string>}\n */\n public function importOpportunityBatchByIds(array $crmIds): array\n {\n $fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);\n\n $allDeals = [];\n foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {\n $deals = $this->client->getOpportunitiesByIds($chunk, $fields);\n foreach ($deals as $deal) {\n $allDeals[] = $deal;\n }\n }\n\n // IDs not returned by HubSpot are likely deleted or inaccessible deals.\n // These are not failures — retrying won't bring them back.\n $fetchedIds = array_map('strval', array_column($allDeals, 'id'));\n $notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));\n\n if (! empty($notFoundIds)) {\n $this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [\n 'teamId' => $this->team->getId(),\n 'notFoundCount' => \\count($notFoundIds),\n 'notFoundIds' => $notFoundIds,\n 'requestedCount' => \\count($crmIds),\n 'fetchedCount' => \\count($allDeals),\n ]);\n }\n\n if (empty($allDeals)) {\n return ['success' => [], 'failed_ids' => []];\n }\n\n return $this->importOpportunityBatch($allDeals);\n }\n\n private function getClosedDealStages(): array\n {\n if ($this->cachedClosedDealStages !== null) {\n return $this->cachedClosedDealStages;\n }\n\n $stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);\n $data = [\n 'lost' => [],\n 'won' => [],\n ];\n\n foreach ($stages as $stage) {\n if ($stage->probability == 0.00) {\n $data['lost'][] = $stage->crm_provider_id;\n }\n if ($stage->probability == 100.00) {\n $data['won'][] = $stage->crm_provider_id;\n }\n }\n\n $this->cachedClosedDealStages = $data;\n\n return $data;\n }\n\n /**\n * Import deals into the database with pre-fetched associations.\n *\n * API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT\n * caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()\n * where Laravel retries the whole job with backoff. After all retries exhausted,\n * failed() requeues all IDs to Redis.\n *\n * The per-deal loop catches exceptions individually. A deal can end up in three states:\n * - success: imported/updated successfully\n * - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)\n * These are permanent issues — retrying won't fix them.\n * - skipped (null): missing dependencies (no account, unknown pipeline/stage).\n * This is acceptable — the deal cannot be imported until those exist.\n */\n private function importOpportunityBatch(array $deals): array\n {\n $syncedOpportunities = [\n 'success' => [],\n 'failed_ids' => [],\n ];\n $dealIds = array_column($deals, 'id');\n\n // Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the\n // queue job retries the whole batch and eventually requeues all deal IDs back to Redis.\n try {\n $companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');\n $contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');\n\n $associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);\n\n $existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(\n $this->config,\n array_map('strval', $dealIds)\n );\n $existingCrmIdSet = array_flip($existingCrmIds);\n } catch (\\Throwable $e) {\n $this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [\n 'teamId' => $this->team->getId(),\n 'dealCount' => count($dealIds),\n 'error' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n foreach ($deals as $deal) {\n try {\n $deal['associations'] = $this->prepareAssociationsForOpportunity(\n $deal['id'],\n $companyAssociations,\n $contactAssociations,\n $associationsData\n );\n\n $syncedOpportunity = $this->importOrUpdateOpportunity(\n $deal,\n isset($existingCrmIdSet[(string) $deal['id']])\n );\n if ($syncedOpportunity) {\n $syncedOpportunities['success'][] = $syncedOpportunity;\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [\n 'teamId' => $this->team->getId(),\n 'crmId' => $deal['id'],\n 'error' => $e->getMessage(),\n ]);\n $syncedOpportunities['failed_ids'][] = $deal['id'];\n $syncedOpportunities['errors'][$deal['id']] = $e->getMessage();\n }\n }\n\n return $syncedOpportunities;\n }\n\n /**\n * Prepare associated entities for opportunities with optimized batch processing\n * Returns structured data with CRM ID to DB ID mappings for each opportunity\n */\n private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array\n {\n // Step 1: Collect all unique company and contact IDs from associations\n $allCompanyIds = $this->flattenAssociationIds($companyAssociations);\n $allContactIds = $this->flattenAssociationIds($contactAssociations);\n\n // Step 2: Batch sync missing entities and get CRM ID to DB ID mappings\n $companyIdMappings = [];\n $contactIdMappings = [];\n\n if (! empty($allCompanyIds)) {\n $companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);\n }\n\n if (! empty($allContactIds)) {\n $contactIdMappings = $this->prepareAssociatedContacts($allContactIds);\n }\n\n return [\n 'company_id_mappings' => $companyIdMappings,\n 'contact_id_mappings' => $contactIdMappings,\n ];\n }\n\n /**\n * Flatten association data to get unique IDs\n */\n private function flattenAssociationIds(array $associations): array\n {\n $ids = [];\n foreach ($associations as $dealAssociations) {\n if (is_array($dealAssociations)) {\n foreach ($dealAssociations as $id) {\n $ids[$id] = true;\n }\n }\n }\n\n return array_keys($ids);\n }\n\n /**\n * Batch sync missing accounts\n */\n private function prepareAssociatedAccounts(array $companyIds): array\n {\n // Find which accounts already exist\n $existingAccounts = $this->crmEntityRepository\n ->findAccountsByExternalIds($this->config, $companyIds);\n\n $existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();\n\n $existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {\n return [$account->getCrmProviderId() => $account->getId()];\n })->toArray();\n\n $missingCompanyIds = array_diff($companyIds, $existingCompanyIds);\n\n if (empty($missingCompanyIds)) {\n return $existingAccountsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [\n 'teamId' => $this->team->getUuid(),\n 'total_companies' => count($companyIds),\n 'existing_companies' => count($existingCompanyIds),\n 'missing_companies' => count($missingCompanyIds),\n ]);\n\n // we already have limit on opportunity ids count\n // Initialize variable before try block\n $syncedAccountsData = [];\n\n try {\n $syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [\n 'size' => count($missingCompanyIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedAccountsData = [];\n }\n\n return $existingAccountsData + $syncedAccountsData;\n }\n\n /**\n * Prepare associated contacts - find existing and sync missing ones\n * Returns mapping of CRM ID to DB ID\n */\n private function prepareAssociatedContacts(array $contactIds): array\n {\n // Find which contacts already exist\n $existingContacts = $this->crmEntityRepository\n ->findContactsByExternalIds($this->config, $contactIds);\n\n $existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();\n\n // Create mapping for existing contacts\n $existingContactsData = $existingContacts->mapWithKeys(function ($contact) {\n return [$contact->getCrmProviderId() => $contact->getId()];\n })->toArray();\n\n $missingContactIds = array_diff($contactIds, $existingContactIds);\n\n if (empty($missingContactIds)) {\n return $existingContactsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [\n 'teamId' => $this->team->getUuid(),\n 'total_contacts' => count($contactIds),\n 'existing_contacts' => count($existingContactIds),\n 'missing_contacts' => count($missingContactIds),\n ]);\n\n // Sync missing contacts using batch API\n try {\n $syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [\n 'size' => count($missingContactIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedContactsData = [];\n }\n\n return $existingContactsData + $syncedContactsData;\n }\n\n private function batchSyncCrmObjects(string $objectType, array $crmIds): array\n {\n $syncObjects = [];\n $crmObjectIds = array_values($crmIds);\n\n foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {\n try {\n $objects = $objectType === 'companies' ?\n $this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :\n $this->client->getContactsByIds($chunk, $this->getContactFields());\n\n foreach ($objects as $objectId => $objectData) {\n $this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [\n 'requested_count' => count($chunk),\n 'synced_count' => count($objects),\n ]);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [\n 'ids' => $chunk,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n return $syncObjects;\n }\n\n private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void\n {\n try {\n $object = $objectType === 'companies' ?\n $this->importAccount($objectData) :\n $this->importContact($objectData);\n\n if ($object) {\n $syncObjects[$object->getCrmProviderId()] = $object->getId();\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [\n 'id' => $objectId,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * Prepare associations for a single opportunity\n *\n * The return value is an array with the following structure:\n * [\n * 'companies' => [\n * $companyCrmId => $companyId,\n * ...\n * ],\n * 'contacts' => [\n * $contactCrmId => $contactId,\n * ...\n * ],\n * 'account_id' => $accountId,\n * ]\n */\n private function prepareAssociationsForOpportunity(\n string $oppCrmId,\n array $companyAssociations,\n array $contactAssociations,\n array $associationsData\n ): array {\n $associations = [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n\n $oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];\n foreach ($oppCompanyIds as $companyCrmId) {\n if (isset($associationsData['company_id_mappings'][$companyCrmId])) {\n $associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];\n\n // Set primary account (first company becomes primary account)\n if ($associations['account_id'] === null) {\n $associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];\n }\n }\n }\n\n $oppContactIds = $contactAssociations[$oppCrmId] ?? [];\n foreach ($oppContactIds as $contactCrmId) {\n if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {\n $associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];\n }\n }\n\n return $associations;\n }\n\n /**\n * Update only associations for an opportunity\n */\n private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void\n {\n // Update contact associations\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n // Update company (account) associations\n $this->updateOpportunityAccount($opportunity, $associations['account_id']);\n }\n\n /**\n * Remove all contact associations from an opportunity\n */\n private function removeAllOpportunityContacts(Opportunity $opportunity): void\n {\n $currentCount = (int) $opportunity->contacts()->count();\n\n if ($currentCount > 0) {\n $opportunity->contacts()->detach();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_count' => $currentCount,\n ]);\n }\n }\n\n private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void\n {\n if ($accountId === null) {\n // No account ID provided - keep current account\n return;\n }\n\n $currentAccountId = $opportunity->getAccountId();\n\n // Only update if account has changed\n if ($currentAccountId !== $accountId) {\n $opportunity->account_id = $accountId;\n $opportunity->save();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [\n 'opportunity_id' => $opportunity->getId(),\n 'old_account_id' => $currentAccountId,\n 'new_account_id' => $accountId,\n ]);\n }\n }\n\n /**\n * Find existing opportunities by external IDs (OPTIMIZED VERSION)\n * Uses batch query for better performance\n */\n private function findExistingOpportunities(array $crmIds): Collection\n {\n return $this->crmEntityRepository\n ->findOpportunitiesByExternalIds($this->config, $crmIds);\n }\n\n private function processOpportunityBatch(array $opportunities): int\n {\n $syncedOpportunities = $this->importOpportunityBatch($opportunities);\n\n return count($syncedOpportunities['success'] ?? []);\n }\n\n /**\n * Convert single deal associations from HubSpot format to internal format\n * Handles both HubSpot SDK objects and array formats\n *\n * @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed\n *\n * @return array Processed associations with DB IDs\n */\n private function convertDealAssociations(array $opportunityAssociations): array\n {\n $associations = $this->initializeAssociationsStructure();\n\n if (empty($opportunityAssociations)) {\n return $associations;\n }\n\n $associationIds = $this->extractAssociationIds($opportunityAssociations);\n\n $this->processCompanyAssociations($associationIds, $associations);\n $this->processContactAssociations($associationIds, $associations);\n\n return $associations;\n }\n\n private function initializeAssociationsStructure(): array\n {\n return [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n }\n\n private function extractAssociationIds(array $opportunityAssociations): array\n {\n $associationIds = [];\n\n foreach ($opportunityAssociations as $type => $associationData) {\n if (! empty($associationData)) {\n $associationIds[$type] = $this->convertSingleDealAssociations($associationData);\n }\n }\n\n return $associationIds;\n }\n\n private function processCompanyAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['companies'])) {\n return;\n }\n\n $companyId = $associationIds['companies'][0];\n $account = $this->findOrSyncAccount($companyId);\n\n if ($account instanceof Account) {\n $associations['companies'][$companyId] = $account->getId();\n $associations['account_id'] = $account->getId();\n }\n }\n\n private function processContactAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['contacts'])) {\n return;\n }\n\n foreach ($associationIds['contacts'] as $contactId) {\n $contact = $this->findOrSyncContact($contactId);\n\n if ($contact instanceof Contact) {\n $associations['contacts'][$contactId] = $contact->getId();\n }\n }\n }\n\n private function findOrSyncAccount(string $companyId): ?Account\n {\n $account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);\n\n if (! $account instanceof Account) {\n $account = $this->syncAccount($companyId);\n }\n\n return $account;\n }\n\n private function findOrSyncContact(string $contactId): ?Contact\n {\n $contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);\n\n if (! $contact instanceof Contact) {\n $contact = $this->syncContact($contactId);\n }\n\n return $contact;\n }\n\n private function convertSingleDealAssociations($opportunityAssociations = null): array\n {\n $associationData = [];\n\n if ($opportunityAssociations === null) {\n return $associationData;\n }\n\n // Handle array input (from extractAssociationIds)\n if (is_array($opportunityAssociations)) {\n return $opportunityAssociations;\n }\n\n // Handle CollectionResponseAssociatedId object\n if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {\n foreach ($opportunityAssociations->getResults() as $association) {\n $associationData[] = $association->getId();\n }\n }\n\n return $associationData;\n }\n\n private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity\n {\n if (empty($crmData['properties'])) {\n return null;\n }\n\n $crmId = (string) $crmData['id'];\n $properties = $crmData['properties'];\n $associations = $crmData['associations'] ?? [];\n\n $opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(\n $this->config,\n $crmId\n );\n\n if ($opportunityExists) {\n return $this->updateOpportunity($crmId, $properties, $associations);\n } else {\n return $this->createOpportunity($crmId, $properties, $associations);\n }\n }\n\n /**\n * Create new opportunity\n */\n private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n if (! $accountId) {\n return null;\n }\n\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n if (! $businessProcess) {\n return null;\n }\n\n $stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);\n if (! $stage) {\n return null;\n }\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n }\n\n /**\n * Update existing opportunity\n */\n private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n $stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->updateOpportunityAssociations($opportunity, $associations);\n\n return $opportunity;\n }\n\n private function resolveAccountId(array $associations): ?int\n {\n if (! empty($associations['accountId'])) {\n return $associations['accountId'];\n }\n\n if (empty($associations)) {\n return null;\n }\n\n // we can't resolve multiple account ids (currently SDK returns one company)\n foreach ($associations['companies'] as $accountId) {\n return $accountId;\n }\n\n return null;\n }\n\n private function buildOpportunityData(\n array $properties,\n ?int $accountId,\n ?BusinessProcess $businessProcess,\n ?Stage $stage\n ): array {\n $ownerId = null;\n $profile = null;\n if (! empty($properties['hubspot_owner_id'])) {\n $ownerId = $properties['hubspot_owner_id'];\n $profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);\n }\n\n $name = 'Unknown';\n if (isset($properties['dealname'])) {\n $name = mb_strimwidth($properties['dealname'], 0, 128);\n }\n\n $amount = $this->resolveAmount($properties);\n $currency = $properties['deal_currency_code'] ?? null;\n\n $closeDate = null;\n if (! empty($properties['closedate'])) {\n $closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');\n }\n\n $remotelyCreatedAt = null;\n if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {\n $date = $this->parseCleanDatetime($properties['createdate']);\n $remotelyCreatedAt = $date?->format('Y-m-d H:i:s');\n }\n\n $closedStages = $this->getClosedDealStages();\n $isWon = in_array($properties['dealstage'], $closedStages['won']);\n $isLost = in_array($properties['dealstage'], $closedStages['lost']);\n\n $data = [\n 'team_id' => $this->team->getId(),\n 'user_id' => $profile ? $profile->user_id : null,\n 'owner_id' => $ownerId,\n 'name' => $name,\n 'value' => ! empty($amount) ? $amount : null,\n 'currency_code' => CurrencyFormatter::formatCode($currency),\n 'close_date' => $closeDate,\n 'is_closed' => $isWon || $isLost,\n 'is_won' => $isWon,\n 'remotely_created_at' => $remotelyCreatedAt,\n 'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),\n 'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),\n ];\n\n if ($accountId) {\n $data['account_id'] = $accountId;\n }\n\n if ($stage) {\n $data['stage_id'] = $stage->id;\n }\n\n if ($businessProcess) {\n $recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);\n if ($recordType) {\n $data['record_type_id'] = $recordType->id;\n }\n }\n\n return $data;\n }\n\n private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess\n {\n if ($pipelineId === null) {\n return null;\n }\n\n if (isset($this->cachedBusinessProcesses[$pipelineId])) {\n return $this->cachedBusinessProcesses[$pipelineId];\n }\n\n $businessProcess = $this->getBusinessProcess($pipelineId);\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->importStages();\n $businessProcess = $this->getBusinessProcess($pipelineId);\n }\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->logger->info(\n '[HubSpot] Deal is not attached to a pipeline',\n [\n 'pipeline' => $pipelineId]\n );\n }\n\n $this->cachedBusinessProcesses[$pipelineId] = $businessProcess;\n\n return $businessProcess;\n }\n\n private function getBusinessProcess(string $pipelineId): ?BusinessProcess\n {\n return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);\n }\n\n private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage\n {\n if (empty($stageId)) {\n return null;\n }\n\n $cacheKey = $businessProcess->getId() . ':' . $stageId;\n if (isset($this->cachedStages[$cacheKey])) {\n return $this->cachedStages[$cacheKey];\n }\n\n $stage = $this->crmEntityRepository->getPipelineStageByConditions(\n $businessProcess,\n [\n 'crm_provider_id' => $stageId,\n 'type' => Stage::TYPE_OPPORTUNITY,\n ]\n );\n\n if ($stage === null) {\n $this->importStages(null, $stageId);\n }\n\n if ($stage === null) {\n $this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);\n }\n\n $this->cachedStages[$cacheKey] = $stage;\n\n return $stage;\n }\n\n private function resolveAmount(array $properties): ?string\n {\n $amount = null;\n if (! empty($properties['amount'])) {\n $amount = str_replace(',', '', $properties['amount']);\n }\n\n if ($this->config->hasDefaultCurrencyFieldSet()) {\n $valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();\n $amount = $properties[$valueFieldName] ?? $amount;\n }\n\n return $amount;\n }\n\n private function parseCleanDatetime(string $datetime): ?Carbon\n {\n // Treat pre-1980 values as invalid\n $minValidDate = Carbon::parse('1980-01-01 00:00:00');\n\n try {\n $date = Carbon::parse($datetime);\n\n if ($minValidDate->gt($date)) {\n return null;\n }\n\n return $date;\n } catch (Exception) {\n return null; // On parse error, treat as null\n }\n }\n\n private function resolveDealProbability(?string $stageProbability): int\n {\n if ($stageProbability === null) {\n return 0;\n }\n\n $probability = (float) $stageProbability;\n\n return $probability > 1 ? 0 : (int) ($probability * 100);\n }\n\n private function resolveForecastCategory(?string $forecastCategory): string\n {\n if (! $forecastCategory) {\n return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;\n }\n\n $forecastCategory = str_replace('_', ' ', $forecastCategory);\n\n return ucwords(strtolower($forecastCategory));\n }\n\n private function importExternalFieldData(array $properties, int $opportunityId): void\n {\n $crmFields = $this->getOpportunitySyncableFields();\n $this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);\n }\n\n private function importOpportunityContacts(Opportunity $opportunity, array $associations): void\n {\n // Handle empty or missing contact associations\n if (empty($associations)) {\n // Remove all existing contact associations if none provided\n $this->removeAllOpportunityContacts($opportunity);\n\n return;\n }\n\n // Use differential sync approach for better performance and accuracy\n $this->syncOpportunityContactsDifferential($opportunity, $associations);\n }\n\n /**\n * Sync opportunity contacts using differential approach\n * This compares current vs new associations and only makes necessary changes\n */\n private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void\n {\n $currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);\n $contactAssociationIds = array_keys($contactAssociations);\n\n $contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);\n $contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);\n\n if (empty($contactsToAdd) && empty($contactsToRemove)) {\n return;\n }\n\n $this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);\n\n $this->removeContactAssociations($opportunity, $contactsToRemove);\n $this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);\n }\n\n private function getCurrentContactCrmIds(Opportunity $opportunity): array\n {\n return $opportunity->contacts()\n ->pluck('contacts.crm_provider_id')\n ->toArray();\n }\n\n private function logContactAssociationChanges(\n Opportunity $opportunity,\n array $currentContactCrmIds,\n array $contactAssociations,\n array $contactsToAdd,\n array $contactsToRemove\n ): void {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [\n 'opportunity_id' => $opportunity->getId(),\n 'current_contacts' => $currentContactCrmIds,\n 'new_contacts' => $contactAssociations,\n 'contacts_to_add' => $contactsToAdd,\n 'contacts_to_remove' => $contactsToRemove,\n ]);\n }\n\n private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void\n {\n if (empty($contactsToRemove)) {\n return;\n }\n\n $contactsToDetach = $opportunity->contacts()\n ->whereIn('contacts.crm_provider_id', $contactsToRemove)\n ->pluck('contacts.id')\n ->toArray();\n\n if (! empty($contactsToDetach)) {\n $opportunity->contacts()->detach($contactsToDetach);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_contact_crm_ids' => $contactsToRemove,\n 'removed_contact_count' => count($contactsToDetach),\n ]);\n }\n }\n\n private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void\n {\n if (empty($contactsToAdd)) {\n return;\n }\n\n $contactsAdded = [];\n foreach ($contactsToAdd as $crmId) {\n $id = $contactAssociations[$crmId];\n\n if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {\n $contactsAdded[] = $crmId;\n }\n }\n\n $this->logAddedContacts($opportunity, $contactsAdded);\n }\n\n private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool\n {\n try {\n $contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);\n\n if (! $contact) {\n return false;\n }\n\n return $this->performContactAttachment($opportunity, $contact, $crmId);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [\n 'opportunity_id' => $opportunity->getId(),\n 'contact_crm_id' => $crmId,\n 'error' => $e->getMessage(),\n ]);\n\n return false;\n }\n }\n\n private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool\n {\n try {\n $opportunity->contacts()->attach($contact->getId(), [\n 'crm_provider_id' => $crmId,\n ]);\n\n return true;\n } catch (\\Illuminate\\Database\\QueryException $e) {\n if (str_contains($e->getMessage(), 'Duplicate entry')) {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [\n 'contact_id' => $contact->getId(),\n 'contact_crm_id' => $crmId,\n 'opportunity_id' => $opportunity->getId(),\n ]);\n\n return false;\n }\n\n throw $e;\n }\n }\n\n private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void\n {\n if (! empty($contactsAdded)) {\n $this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'contacts_to_add_count' => count($contactsAdded),\n 'added_contact_crm_ids' => $contactsAdded,\n 'added_contacts_count' => count($contactsAdded),\n ]);\n }\n }\n}","depth":4,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\CollectionResponseAssociatedId;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\Account;\nuse Exception;\nuse Jiminny\\Component\\DealInsights\\Forecast\\Forecast;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Models\\Opportunity;\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Repositories\\Crm\\CrmEntityRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DealFieldsService;\nuse Jiminny\\Services\\Crm\\Hubspot\\OpportunitySyncStrategy\\HubspotSingleSyncStrategy;\nuse Jiminny\\Services\\Crm\\Hubspot\\WebhookSyncBatchProcessor;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Utils\\CurrencyFormatter;\n\n/**\n * Optimized sync methods for better performance\n * These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains\n */\ntrait OpportunitySyncTrait\n{\n private const int BATCH_SIZE = 100;\n private const int BATCH_PROCESS_SIZE = 800;\n\n protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n protected CrmEntityRepository $crmEntityRepository;\n protected DealFieldsService $dealFieldsService;\n\n private ?array $cachedClosedDealStages = null;\n private array $cachedBusinessProcesses = [];\n private array $cachedStages = [];\n\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n $parameters['config'] = $this->config;\n $syncCount = 0;\n $reportedTotal = 0;\n $lastSyncedId = [];\n\n try {\n foreach ($strategies as $strategyName => $syncStrategy) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .\n $strategyName\n );\n\n $total = 0;\n $lastId = null;\n $buffer = [];\n\n // HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies\n foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {\n $buffer[] = $hsOpportunity;\n\n // process every 800 rows (fits < 1 000 association limit)\n if (\\count($buffer) >= self::BATCH_PROCESS_SIZE) {\n $syncCount += $this->processOpportunityBatch($buffer);\n $buffer = [];\n }\n }\n\n // leftovers\n if ($buffer) {\n $syncCount += $this->processOpportunityBatch($buffer);\n }\n\n $reportedTotal += $total;\n $lastSyncedId = $lastId;\n }\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException | CrmException $e) {\n $this->handleSyncException($e, $parameters);\n }\n\n $this->logger->info(\n '[HubSpot] Synced opportunities',\n [\n 'team' => $this->team->getId(),\n 'sync_count' => $syncCount,\n 'total' => $reportedTotal,\n 'last_synced_id' => $lastSyncedId,\n ]\n );\n\n return $reportedTotal;\n }\n\n private function handleSyncException(\\Throwable $e, array $parameters): void\n {\n if (($parameters['since'] ?? null) instanceof Carbon) {\n $parameters['since'] = $parameters['since']->toDateTimeString();\n }\n $parameters['config'] = $this->config->getId();\n\n $this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [\n 'teamId' => $this->team->getUuid(),\n 'parameters' => $parameters,\n 'reason' => $e->getMessage(),\n ]);\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,\n );\n\n $parameters = [\n 'config' => $this->config,\n 'crm_id' => $crmId,\n ];\n\n try {\n if (! $strategy instanceof HubspotSingleSyncStrategy) {\n throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');\n }\n\n $hsOpportunity = $strategy->fetchOpportunity($parameters);\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->getUuid(),\n 'crmId' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);\n\n return $this->importOrUpdateOpportunity($hsOpportunity);\n }\n\n /**\n * Process webhook-collected opportunity batches.\n *\n * Drains Redis sets containing company CRM IDs collected from webhook events\n * and dispatches ImportOpportunityBatch jobs for batch processing.\n *\n * @return int Number of opportunity IDs dispatched to jobs\n */\n public function batchSyncOpportunities(): int\n {\n $configId = $this->team->getCrmConfiguration()->getId();\n\n return $this->batchProcessor->processBatchesForObjectType(\n WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,\n $configId\n );\n }\n\n /**\n * Import a batch of opportunities by their CRM IDs.\n * Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().\n *\n * @param array<string> $crmIds HubSpot deal CRM IDs\n *\n * @return array{success: array, failed_ids: array, errors?: array<string, string>}\n */\n public function importOpportunityBatchByIds(array $crmIds): array\n {\n $fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);\n\n $allDeals = [];\n foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {\n $deals = $this->client->getOpportunitiesByIds($chunk, $fields);\n foreach ($deals as $deal) {\n $allDeals[] = $deal;\n }\n }\n\n // IDs not returned by HubSpot are likely deleted or inaccessible deals.\n // These are not failures — retrying won't bring them back.\n $fetchedIds = array_map('strval', array_column($allDeals, 'id'));\n $notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));\n\n if (! empty($notFoundIds)) {\n $this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [\n 'teamId' => $this->team->getId(),\n 'notFoundCount' => \\count($notFoundIds),\n 'notFoundIds' => $notFoundIds,\n 'requestedCount' => \\count($crmIds),\n 'fetchedCount' => \\count($allDeals),\n ]);\n }\n\n if (empty($allDeals)) {\n return ['success' => [], 'failed_ids' => []];\n }\n\n return $this->importOpportunityBatch($allDeals);\n }\n\n private function getClosedDealStages(): array\n {\n if ($this->cachedClosedDealStages !== null) {\n return $this->cachedClosedDealStages;\n }\n\n $stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);\n $data = [\n 'lost' => [],\n 'won' => [],\n ];\n\n foreach ($stages as $stage) {\n if ($stage->probability == 0.00) {\n $data['lost'][] = $stage->crm_provider_id;\n }\n if ($stage->probability == 100.00) {\n $data['won'][] = $stage->crm_provider_id;\n }\n }\n\n $this->cachedClosedDealStages = $data;\n\n return $data;\n }\n\n /**\n * Import deals into the database with pre-fetched associations.\n *\n * API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT\n * caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()\n * where Laravel retries the whole job with backoff. After all retries exhausted,\n * failed() requeues all IDs to Redis.\n *\n * The per-deal loop catches exceptions individually. A deal can end up in three states:\n * - success: imported/updated successfully\n * - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)\n * These are permanent issues — retrying won't fix them.\n * - skipped (null): missing dependencies (no account, unknown pipeline/stage).\n * This is acceptable — the deal cannot be imported until those exist.\n */\n private function importOpportunityBatch(array $deals): array\n {\n $syncedOpportunities = [\n 'success' => [],\n 'failed_ids' => [],\n ];\n $dealIds = array_column($deals, 'id');\n\n // Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the\n // queue job retries the whole batch and eventually requeues all deal IDs back to Redis.\n try {\n $companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');\n $contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');\n\n $associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);\n\n $existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(\n $this->config,\n array_map('strval', $dealIds)\n );\n $existingCrmIdSet = array_flip($existingCrmIds);\n } catch (\\Throwable $e) {\n $this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [\n 'teamId' => $this->team->getId(),\n 'dealCount' => count($dealIds),\n 'error' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n foreach ($deals as $deal) {\n try {\n $deal['associations'] = $this->prepareAssociationsForOpportunity(\n $deal['id'],\n $companyAssociations,\n $contactAssociations,\n $associationsData\n );\n\n $syncedOpportunity = $this->importOrUpdateOpportunity(\n $deal,\n isset($existingCrmIdSet[(string) $deal['id']])\n );\n if ($syncedOpportunity) {\n $syncedOpportunities['success'][] = $syncedOpportunity;\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [\n 'teamId' => $this->team->getId(),\n 'crmId' => $deal['id'],\n 'error' => $e->getMessage(),\n ]);\n $syncedOpportunities['failed_ids'][] = $deal['id'];\n $syncedOpportunities['errors'][$deal['id']] = $e->getMessage();\n }\n }\n\n return $syncedOpportunities;\n }\n\n /**\n * Prepare associated entities for opportunities with optimized batch processing\n * Returns structured data with CRM ID to DB ID mappings for each opportunity\n */\n private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array\n {\n // Step 1: Collect all unique company and contact IDs from associations\n $allCompanyIds = $this->flattenAssociationIds($companyAssociations);\n $allContactIds = $this->flattenAssociationIds($contactAssociations);\n\n // Step 2: Batch sync missing entities and get CRM ID to DB ID mappings\n $companyIdMappings = [];\n $contactIdMappings = [];\n\n if (! empty($allCompanyIds)) {\n $companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);\n }\n\n if (! empty($allContactIds)) {\n $contactIdMappings = $this->prepareAssociatedContacts($allContactIds);\n }\n\n return [\n 'company_id_mappings' => $companyIdMappings,\n 'contact_id_mappings' => $contactIdMappings,\n ];\n }\n\n /**\n * Flatten association data to get unique IDs\n */\n private function flattenAssociationIds(array $associations): array\n {\n $ids = [];\n foreach ($associations as $dealAssociations) {\n if (is_array($dealAssociations)) {\n foreach ($dealAssociations as $id) {\n $ids[$id] = true;\n }\n }\n }\n\n return array_keys($ids);\n }\n\n /**\n * Batch sync missing accounts\n */\n private function prepareAssociatedAccounts(array $companyIds): array\n {\n // Find which accounts already exist\n $existingAccounts = $this->crmEntityRepository\n ->findAccountsByExternalIds($this->config, $companyIds);\n\n $existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();\n\n $existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {\n return [$account->getCrmProviderId() => $account->getId()];\n })->toArray();\n\n $missingCompanyIds = array_diff($companyIds, $existingCompanyIds);\n\n if (empty($missingCompanyIds)) {\n return $existingAccountsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [\n 'teamId' => $this->team->getUuid(),\n 'total_companies' => count($companyIds),\n 'existing_companies' => count($existingCompanyIds),\n 'missing_companies' => count($missingCompanyIds),\n ]);\n\n // we already have limit on opportunity ids count\n // Initialize variable before try block\n $syncedAccountsData = [];\n\n try {\n $syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [\n 'size' => count($missingCompanyIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedAccountsData = [];\n }\n\n return $existingAccountsData + $syncedAccountsData;\n }\n\n /**\n * Prepare associated contacts - find existing and sync missing ones\n * Returns mapping of CRM ID to DB ID\n */\n private function prepareAssociatedContacts(array $contactIds): array\n {\n // Find which contacts already exist\n $existingContacts = $this->crmEntityRepository\n ->findContactsByExternalIds($this->config, $contactIds);\n\n $existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();\n\n // Create mapping for existing contacts\n $existingContactsData = $existingContacts->mapWithKeys(function ($contact) {\n return [$contact->getCrmProviderId() => $contact->getId()];\n })->toArray();\n\n $missingContactIds = array_diff($contactIds, $existingContactIds);\n\n if (empty($missingContactIds)) {\n return $existingContactsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [\n 'teamId' => $this->team->getUuid(),\n 'total_contacts' => count($contactIds),\n 'existing_contacts' => count($existingContactIds),\n 'missing_contacts' => count($missingContactIds),\n ]);\n\n // Sync missing contacts using batch API\n try {\n $syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [\n 'size' => count($missingContactIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedContactsData = [];\n }\n\n return $existingContactsData + $syncedContactsData;\n }\n\n private function batchSyncCrmObjects(string $objectType, array $crmIds): array\n {\n $syncObjects = [];\n $crmObjectIds = array_values($crmIds);\n\n foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {\n try {\n $objects = $objectType === 'companies' ?\n $this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :\n $this->client->getContactsByIds($chunk, $this->getContactFields());\n\n foreach ($objects as $objectId => $objectData) {\n $this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [\n 'requested_count' => count($chunk),\n 'synced_count' => count($objects),\n ]);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [\n 'ids' => $chunk,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n return $syncObjects;\n }\n\n private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void\n {\n try {\n $object = $objectType === 'companies' ?\n $this->importAccount($objectData) :\n $this->importContact($objectData);\n\n if ($object) {\n $syncObjects[$object->getCrmProviderId()] = $object->getId();\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [\n 'id' => $objectId,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * Prepare associations for a single opportunity\n *\n * The return value is an array with the following structure:\n * [\n * 'companies' => [\n * $companyCrmId => $companyId,\n * ...\n * ],\n * 'contacts' => [\n * $contactCrmId => $contactId,\n * ...\n * ],\n * 'account_id' => $accountId,\n * ]\n */\n private function prepareAssociationsForOpportunity(\n string $oppCrmId,\n array $companyAssociations,\n array $contactAssociations,\n array $associationsData\n ): array {\n $associations = [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n\n $oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];\n foreach ($oppCompanyIds as $companyCrmId) {\n if (isset($associationsData['company_id_mappings'][$companyCrmId])) {\n $associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];\n\n // Set primary account (first company becomes primary account)\n if ($associations['account_id'] === null) {\n $associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];\n }\n }\n }\n\n $oppContactIds = $contactAssociations[$oppCrmId] ?? [];\n foreach ($oppContactIds as $contactCrmId) {\n if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {\n $associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];\n }\n }\n\n return $associations;\n }\n\n /**\n * Update only associations for an opportunity\n */\n private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void\n {\n // Update contact associations\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n // Update company (account) associations\n $this->updateOpportunityAccount($opportunity, $associations['account_id']);\n }\n\n /**\n * Remove all contact associations from an opportunity\n */\n private function removeAllOpportunityContacts(Opportunity $opportunity): void\n {\n $currentCount = (int) $opportunity->contacts()->count();\n\n if ($currentCount > 0) {\n $opportunity->contacts()->detach();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_count' => $currentCount,\n ]);\n }\n }\n\n private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void\n {\n if ($accountId === null) {\n // No account ID provided - keep current account\n return;\n }\n\n $currentAccountId = $opportunity->getAccountId();\n\n // Only update if account has changed\n if ($currentAccountId !== $accountId) {\n $opportunity->account_id = $accountId;\n $opportunity->save();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [\n 'opportunity_id' => $opportunity->getId(),\n 'old_account_id' => $currentAccountId,\n 'new_account_id' => $accountId,\n ]);\n }\n }\n\n /**\n * Find existing opportunities by external IDs (OPTIMIZED VERSION)\n * Uses batch query for better performance\n */\n private function findExistingOpportunities(array $crmIds): Collection\n {\n return $this->crmEntityRepository\n ->findOpportunitiesByExternalIds($this->config, $crmIds);\n }\n\n private function processOpportunityBatch(array $opportunities): int\n {\n $syncedOpportunities = $this->importOpportunityBatch($opportunities);\n\n return count($syncedOpportunities['success'] ?? []);\n }\n\n /**\n * Convert single deal associations from HubSpot format to internal format\n * Handles both HubSpot SDK objects and array formats\n *\n * @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed\n *\n * @return array Processed associations with DB IDs\n */\n private function convertDealAssociations(array $opportunityAssociations): array\n {\n $associations = $this->initializeAssociationsStructure();\n\n if (empty($opportunityAssociations)) {\n return $associations;\n }\n\n $associationIds = $this->extractAssociationIds($opportunityAssociations);\n\n $this->processCompanyAssociations($associationIds, $associations);\n $this->processContactAssociations($associationIds, $associations);\n\n return $associations;\n }\n\n private function initializeAssociationsStructure(): array\n {\n return [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n }\n\n private function extractAssociationIds(array $opportunityAssociations): array\n {\n $associationIds = [];\n\n foreach ($opportunityAssociations as $type => $associationData) {\n if (! empty($associationData)) {\n $associationIds[$type] = $this->convertSingleDealAssociations($associationData);\n }\n }\n\n return $associationIds;\n }\n\n private function processCompanyAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['companies'])) {\n return;\n }\n\n $companyId = $associationIds['companies'][0];\n $account = $this->findOrSyncAccount($companyId);\n\n if ($account instanceof Account) {\n $associations['companies'][$companyId] = $account->getId();\n $associations['account_id'] = $account->getId();\n }\n }\n\n private function processContactAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['contacts'])) {\n return;\n }\n\n foreach ($associationIds['contacts'] as $contactId) {\n $contact = $this->findOrSyncContact($contactId);\n\n if ($contact instanceof Contact) {\n $associations['contacts'][$contactId] = $contact->getId();\n }\n }\n }\n\n private function findOrSyncAccount(string $companyId): ?Account\n {\n $account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);\n\n if (! $account instanceof Account) {\n $account = $this->syncAccount($companyId);\n }\n\n return $account;\n }\n\n private function findOrSyncContact(string $contactId): ?Contact\n {\n $contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);\n\n if (! $contact instanceof Contact) {\n $contact = $this->syncContact($contactId);\n }\n\n return $contact;\n }\n\n private function convertSingleDealAssociations($opportunityAssociations = null): array\n {\n $associationData = [];\n\n if ($opportunityAssociations === null) {\n return $associationData;\n }\n\n // Handle array input (from extractAssociationIds)\n if (is_array($opportunityAssociations)) {\n return $opportunityAssociations;\n }\n\n // Handle CollectionResponseAssociatedId object\n if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {\n foreach ($opportunityAssociations->getResults() as $association) {\n $associationData[] = $association->getId();\n }\n }\n\n return $associationData;\n }\n\n private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity\n {\n if (empty($crmData['properties'])) {\n return null;\n }\n\n $crmId = (string) $crmData['id'];\n $properties = $crmData['properties'];\n $associations = $crmData['associations'] ?? [];\n\n $opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(\n $this->config,\n $crmId\n );\n\n if ($opportunityExists) {\n return $this->updateOpportunity($crmId, $properties, $associations);\n } else {\n return $this->createOpportunity($crmId, $properties, $associations);\n }\n }\n\n /**\n * Create new opportunity\n */\n private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n if (! $accountId) {\n return null;\n }\n\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n if (! $businessProcess) {\n return null;\n }\n\n $stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);\n if (! $stage) {\n return null;\n }\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n }\n\n /**\n * Update existing opportunity\n */\n private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n $stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->updateOpportunityAssociations($opportunity, $associations);\n\n return $opportunity;\n }\n\n private function resolveAccountId(array $associations): ?int\n {\n if (! empty($associations['accountId'])) {\n return $associations['accountId'];\n }\n\n if (empty($associations)) {\n return null;\n }\n\n // we can't resolve multiple account ids (currently SDK returns one company)\n foreach ($associations['companies'] as $accountId) {\n return $accountId;\n }\n\n return null;\n }\n\n private function buildOpportunityData(\n array $properties,\n ?int $accountId,\n ?BusinessProcess $businessProcess,\n ?Stage $stage\n ): array {\n $ownerId = null;\n $profile = null;\n if (! empty($properties['hubspot_owner_id'])) {\n $ownerId = $properties['hubspot_owner_id'];\n $profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);\n }\n\n $name = 'Unknown';\n if (isset($properties['dealname'])) {\n $name = mb_strimwidth($properties['dealname'], 0, 128);\n }\n\n $amount = $this->resolveAmount($properties);\n $currency = $properties['deal_currency_code'] ?? null;\n\n $closeDate = null;\n if (! empty($properties['closedate'])) {\n $closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');\n }\n\n $remotelyCreatedAt = null;\n if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {\n $date = $this->parseCleanDatetime($properties['createdate']);\n $remotelyCreatedAt = $date?->format('Y-m-d H:i:s');\n }\n\n $closedStages = $this->getClosedDealStages();\n $isWon = in_array($properties['dealstage'], $closedStages['won']);\n $isLost = in_array($properties['dealstage'], $closedStages['lost']);\n\n $data = [\n 'team_id' => $this->team->getId(),\n 'user_id' => $profile ? $profile->user_id : null,\n 'owner_id' => $ownerId,\n 'name' => $name,\n 'value' => ! empty($amount) ? $amount : null,\n 'currency_code' => CurrencyFormatter::formatCode($currency),\n 'close_date' => $closeDate,\n 'is_closed' => $isWon || $isLost,\n 'is_won' => $isWon,\n 'remotely_created_at' => $remotelyCreatedAt,\n 'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),\n 'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),\n ];\n\n if ($accountId) {\n $data['account_id'] = $accountId;\n }\n\n if ($stage) {\n $data['stage_id'] = $stage->id;\n }\n\n if ($businessProcess) {\n $recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);\n if ($recordType) {\n $data['record_type_id'] = $recordType->id;\n }\n }\n\n return $data;\n }\n\n private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess\n {\n if ($pipelineId === null) {\n return null;\n }\n\n if (isset($this->cachedBusinessProcesses[$pipelineId])) {\n return $this->cachedBusinessProcesses[$pipelineId];\n }\n\n $businessProcess = $this->getBusinessProcess($pipelineId);\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->importStages();\n $businessProcess = $this->getBusinessProcess($pipelineId);\n }\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->logger->info(\n '[HubSpot] Deal is not attached to a pipeline',\n [\n 'pipeline' => $pipelineId]\n );\n }\n\n $this->cachedBusinessProcesses[$pipelineId] = $businessProcess;\n\n return $businessProcess;\n }\n\n private function getBusinessProcess(string $pipelineId): ?BusinessProcess\n {\n return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);\n }\n\n private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage\n {\n if (empty($stageId)) {\n return null;\n }\n\n $cacheKey = $businessProcess->getId() . ':' . $stageId;\n if (isset($this->cachedStages[$cacheKey])) {\n return $this->cachedStages[$cacheKey];\n }\n\n $stage = $this->crmEntityRepository->getPipelineStageByConditions(\n $businessProcess,\n [\n 'crm_provider_id' => $stageId,\n 'type' => Stage::TYPE_OPPORTUNITY,\n ]\n );\n\n if ($stage === null) {\n $this->importStages(null, $stageId);\n }\n\n if ($stage === null) {\n $this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);\n }\n\n $this->cachedStages[$cacheKey] = $stage;\n\n return $stage;\n }\n\n private function resolveAmount(array $properties): ?string\n {\n $amount = null;\n if (! empty($properties['amount'])) {\n $amount = str_replace(',', '', $properties['amount']);\n }\n\n if ($this->config->hasDefaultCurrencyFieldSet()) {\n $valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();\n $amount = $properties[$valueFieldName] ?? $amount;\n }\n\n return $amount;\n }\n\n private function parseCleanDatetime(string $datetime): ?Carbon\n {\n // Treat pre-1980 values as invalid\n $minValidDate = Carbon::parse('1980-01-01 00:00:00');\n\n try {\n $date = Carbon::parse($datetime);\n\n if ($minValidDate->gt($date)) {\n return null;\n }\n\n return $date;\n } catch (Exception) {\n return null; // On parse error, treat as null\n }\n }\n\n private function resolveDealProbability(?string $stageProbability): int\n {\n if ($stageProbability === null) {\n return 0;\n }\n\n $probability = (float) $stageProbability;\n\n return $probability > 1 ? 0 : (int) ($probability * 100);\n }\n\n private function resolveForecastCategory(?string $forecastCategory): string\n {\n if (! $forecastCategory) {\n return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;\n }\n\n $forecastCategory = str_replace('_', ' ', $forecastCategory);\n\n return ucwords(strtolower($forecastCategory));\n }\n\n private function importExternalFieldData(array $properties, int $opportunityId): void\n {\n $crmFields = $this->getOpportunitySyncableFields();\n $this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);\n }\n\n private function importOpportunityContacts(Opportunity $opportunity, array $associations): void\n {\n // Handle empty or missing contact associations\n if (empty($associations)) {\n // Remove all existing contact associations if none provided\n $this->removeAllOpportunityContacts($opportunity);\n\n return;\n }\n\n // Use differential sync approach for better performance and accuracy\n $this->syncOpportunityContactsDifferential($opportunity, $associations);\n }\n\n /**\n * Sync opportunity contacts using differential approach\n * This compares current vs new associations and only makes necessary changes\n */\n private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void\n {\n $currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);\n $contactAssociationIds = array_keys($contactAssociations);\n\n $contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);\n $contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);\n\n if (empty($contactsToAdd) && empty($contactsToRemove)) {\n return;\n }\n\n $this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);\n\n $this->removeContactAssociations($opportunity, $contactsToRemove);\n $this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);\n }\n\n private function getCurrentContactCrmIds(Opportunity $opportunity): array\n {\n return $opportunity->contacts()\n ->pluck('contacts.crm_provider_id')\n ->toArray();\n }\n\n private function logContactAssociationChanges(\n Opportunity $opportunity,\n array $currentContactCrmIds,\n array $contactAssociations,\n array $contactsToAdd,\n array $contactsToRemove\n ): void {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [\n 'opportunity_id' => $opportunity->getId(),\n 'current_contacts' => $currentContactCrmIds,\n 'new_contacts' => $contactAssociations,\n 'contacts_to_add' => $contactsToAdd,\n 'contacts_to_remove' => $contactsToRemove,\n ]);\n }\n\n private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void\n {\n if (empty($contactsToRemove)) {\n return;\n }\n\n $contactsToDetach = $opportunity->contacts()\n ->whereIn('contacts.crm_provider_id', $contactsToRemove)\n ->pluck('contacts.id')\n ->toArray();\n\n if (! empty($contactsToDetach)) {\n $opportunity->contacts()->detach($contactsToDetach);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_contact_crm_ids' => $contactsToRemove,\n 'removed_contact_count' => count($contactsToDetach),\n ]);\n }\n }\n\n private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void\n {\n if (empty($contactsToAdd)) {\n return;\n }\n\n $contactsAdded = [];\n foreach ($contactsToAdd as $crmId) {\n $id = $contactAssociations[$crmId];\n\n if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {\n $contactsAdded[] = $crmId;\n }\n }\n\n $this->logAddedContacts($opportunity, $contactsAdded);\n }\n\n private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool\n {\n try {\n $contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);\n\n if (! $contact) {\n return false;\n }\n\n return $this->performContactAttachment($opportunity, $contact, $crmId);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [\n 'opportunity_id' => $opportunity->getId(),\n 'contact_crm_id' => $crmId,\n 'error' => $e->getMessage(),\n ]);\n\n return false;\n }\n }\n\n private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool\n {\n try {\n $opportunity->contacts()->attach($contact->getId(), [\n 'crm_provider_id' => $crmId,\n ]);\n\n return true;\n } catch (\\Illuminate\\Database\\QueryException $e) {\n if (str_contains($e->getMessage(), 'Duplicate entry')) {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [\n 'contact_id' => $contact->getId(),\n 'contact_crm_id' => $crmId,\n 'opportunity_id' => $opportunity->getId(),\n ]);\n\n return false;\n }\n\n throw $e;\n }\n }\n\n private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void\n {\n if (! empty($contactsAdded)) {\n $this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'contacts_to_add_count' => count($contactsAdded),\n 'added_contact_crm_ids' => $contactsAdded,\n 'added_contacts_count' => count($contactsAdded),\n ]);\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.02111111},"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.025555555},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.014583333,"height":0.025555555},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<template>\n <WelcomeLayout\n title=\"Account disconnected\"\n textPosition=\"center\"\n :icon=\"faUnlink\"\n :class=\"$style.layout\"\n >\n <div :class=\"$style.container\" v-if=\"providersLoaded\">\n <p>\n <strong>\n It looks like your {{ localProvider.displayName }} account has become\n disconnected\n </strong>\n </p>\n <p :class=\"$style.small\">Please re-connect to continue</p>\n <p v-if=\"isInIframe\">\n We'll open the {{ localProvider.displayName }} authentication in a new\n tab. Please return here and refresh the page once complete\n </p>\n\n <GoogleLikeButton\n v-if=\"localProvider.viaIntegrationApp && crmTokenLoaded\"\n as=\"a\"\n :key=\"localProvider.name\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n @click=\"integrationAppOnClick\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n <GoogleLikeButton\n v-if=\"!localProvider.viaIntegrationApp\"\n as=\"a\"\n :key=\"localProvider.name\"\n :href=\"`/auth/redirect/${localProvider.name}`\"\n :target=\"target\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n </div>\n <BuildInfo />\n\n <KioskBanner />\n </WelcomeLayout>\n</template>\n\n<script>\nimport window from \"window\";\nimport axios from \"axios\";\nimport { faUnlink } from \"@fortawesome/pro-regular-svg-icons\";\nimport isInIframe from \"@/utils/isInIframe\";\nimport BuildInfo from \"@/components/layout/BuildInfo/BuildInfo.vue\";\nimport KioskBanner from \"@/components/shared/KioskBanner/KioskBanner.vue\";\nimport WelcomeLayout from \"@/components/layout/WelcomeLayout/WelcomeLayout.vue\";\nimport GoogleLikeButton from \"@/components/shared/Buttons/GoogleLikeButton.vue\";\nimport { showSnackbarError, normalizeError } from \"@/utils/index\";\nimport { IntegrationAppClient } from \"@integration-app/sdk\";\n\nexport default {\n name: \"ConnectPage\",\n components: {\n BuildInfo,\n KioskBanner,\n WelcomeLayout,\n GoogleLikeButton,\n },\n data() {\n return {\n ...window.connectData,\n crmToken: null,\n faUnlink,\n isInIframe,\n providers: [],\n providersLoaded: false,\n crmTokenLoaded: false,\n };\n },\n computed: {\n localProvider() {\n return this.providers.find((e) => e.name === this.provider);\n },\n target() {\n return this.isInIframe ? \"_blank\" : null;\n },\n },\n created() {\n this.getProviders();\n },\n mounted() {\n this.showErrors();\n },\n watch: {\n providersLoaded() {\n if (this.providersLoaded) {\n this.prepareIntegrationAppConnection();\n }\n },\n },\n methods: {\n showErrors() {\n if (!this.error) return;\n\n showSnackbarError(this.error, undefined, undefined, false);\n },\n unwrapEntityResponse({ data }) {\n return data.map(({ icon, name, displayName, viaIntegrationApp }) => {\n return { icon, name, displayName, viaIntegrationApp };\n });\n },\n async getProviders() {\n try {\n const response = await axios.get(\"/api/v1/connect-providers\");\n this.providers = this.unwrapEntityResponse(response);\n this.providersLoaded = true;\n } catch {\n showSnackbarError(\n \"An error occurred, while loading form data (connect providers).\",\n );\n }\n },\n async prepareIntegrationAppConnection() {\n if (this.localProvider.viaIntegrationApp) {\n try {\n const response = await axios.get(\"/api/v1/integration-app-token\");\n this.crmToken = response.data.token;\n this.crmTokenLoaded = true;\n } catch (error) {\n console.log(error);\n showSnackbarError(\n `An error occurred while preparing the page.\n Try refreshing, if the error persists get in touch with the Jiminny team.`,\n );\n }\n }\n },\n async integrationAppOnClick() {\n const integrationApp = new IntegrationAppClient({\n token: this.crmToken,\n });\n\n const connection = await integrationApp\n .integration(this.localProvider.name)\n .openNewConnection({\n showPoweredBy: false,\n allowMultipleConnections: false,\n });\n\n console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));\n\n // [IntegrationApp] openNewConnection resolved: {\n // \"id\":\"69e0b41a67d0068c2ca0b48e\",\n // \"name\":\"Zoho CRM\",\n // \"userId\":\"1ece66c8-feb1-4df1-b321-21607daf4623\",\n // \"tenantId\":\"69e0b3faef3e7b6248189289\",\n // \"isTest\":false,\n // \"connected\":true,\n // \"state\":\"READY\",\n // \"errors\":[],\n // \"integrationId\":\"66fe6c913202f3a165e3c14d\",\n // \"externalAppId\":\"6671653e7e2d642e4e41b0fa\",\n // \"authOptionKey\":\"\",\n // \"createdAt\":\"2026-04-16T10:04:10.420Z\",\n // \"updatedAt\":\"2026-04-16T10:04:10.575Z\",\n // \"retryAttempts\":0,\n // \"isDeactivated\":false\n // }\n\n if (connection && connection.disconnected !== true && connection.connected !== false) {\n console.log('[IntegrationApp] connection condition matched');\n try {\n const saveRequest = await axios.post(\n \"/api/v1/integration-app-connect\",\n );\n if (saveRequest.data && saveRequest.data.success === true) {\n /** If all is good refresh the page here */\n window.location = \"/dashboard\";\n return;\n }\n\n throw new Error(saveRequest.data.message);\n } catch (error) {\n console.log(error);\n showSnackbarError(normalizeError(error));\n }\n }\n },\n },\n};\n</script>\n\n<style module lang=\"less\" src=\"./connect.less\"></style>","depth":4,"value":"<template>\n <WelcomeLayout\n title=\"Account disconnected\"\n textPosition=\"center\"\n :icon=\"faUnlink\"\n :class=\"$style.layout\"\n >\n <div :class=\"$style.container\" v-if=\"providersLoaded\">\n <p>\n <strong>\n It looks like your {{ localProvider.displayName }} account has become\n disconnected\n </strong>\n </p>\n <p :class=\"$style.small\">Please re-connect to continue</p>\n <p v-if=\"isInIframe\">\n We'll open the {{ localProvider.displayName }} authentication in a new\n tab. Please return here and refresh the page once complete\n </p>\n\n <GoogleLikeButton\n v-if=\"localProvider.viaIntegrationApp && crmTokenLoaded\"\n as=\"a\"\n :key=\"localProvider.name\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n @click=\"integrationAppOnClick\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n <GoogleLikeButton\n v-if=\"!localProvider.viaIntegrationApp\"\n as=\"a\"\n :key=\"localProvider.name\"\n :href=\"`/auth/redirect/${localProvider.name}`\"\n :target=\"target\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n </div>\n <BuildInfo />\n\n <KioskBanner />\n </WelcomeLayout>\n</template>\n\n<script>\nimport window from \"window\";\nimport axios from \"axios\";\nimport { faUnlink } from \"@fortawesome/pro-regular-svg-icons\";\nimport isInIframe from \"@/utils/isInIframe\";\nimport BuildInfo from \"@/components/layout/BuildInfo/BuildInfo.vue\";\nimport KioskBanner from \"@/components/shared/KioskBanner/KioskBanner.vue\";\nimport WelcomeLayout from \"@/components/layout/WelcomeLayout/WelcomeLayout.vue\";\nimport GoogleLikeButton from \"@/components/shared/Buttons/GoogleLikeButton.vue\";\nimport { showSnackbarError, normalizeError } from \"@/utils/index\";\nimport { IntegrationAppClient } from \"@integration-app/sdk\";\n\nexport default {\n name: \"ConnectPage\",\n components: {\n BuildInfo,\n KioskBanner,\n WelcomeLayout,\n GoogleLikeButton,\n },\n data() {\n return {\n ...window.connectData,\n crmToken: null,\n faUnlink,\n isInIframe,\n providers: [],\n providersLoaded: false,\n crmTokenLoaded: false,\n };\n },\n computed: {\n localProvider() {\n return this.providers.find((e) => e.name === this.provider);\n },\n target() {\n return this.isInIframe ? \"_blank\" : null;\n },\n },\n created() {\n this.getProviders();\n },\n mounted() {\n this.showErrors();\n },\n watch: {\n providersLoaded() {\n if (this.providersLoaded) {\n this.prepareIntegrationAppConnection();\n }\n },\n },\n methods: {\n showErrors() {\n if (!this.error) return;\n\n showSnackbarError(this.error, undefined, undefined, false);\n },\n unwrapEntityResponse({ data }) {\n return data.map(({ icon, name, displayName, viaIntegrationApp }) => {\n return { icon, name, displayName, viaIntegrationApp };\n });\n },\n async getProviders() {\n try {\n const response = await axios.get(\"/api/v1/connect-providers\");\n this.providers = this.unwrapEntityResponse(response);\n this.providersLoaded = true;\n } catch {\n showSnackbarError(\n \"An error occurred, while loading form data (connect providers).\",\n );\n }\n },\n async prepareIntegrationAppConnection() {\n if (this.localProvider.viaIntegrationApp) {\n try {\n const response = await axios.get(\"/api/v1/integration-app-token\");\n this.crmToken = response.data.token;\n this.crmTokenLoaded = true;\n } catch (error) {\n console.log(error);\n showSnackbarError(\n `An error occurred while preparing the page.\n Try refreshing, if the error persists get in touch with the Jiminny team.`,\n );\n }\n }\n },\n async integrationAppOnClick() {\n const integrationApp = new IntegrationAppClient({\n token: this.crmToken,\n });\n\n const connection = await integrationApp\n .integration(this.localProvider.name)\n .openNewConnection({\n showPoweredBy: false,\n allowMultipleConnections: false,\n });\n\n console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));\n\n // [IntegrationApp] openNewConnection resolved: {\n // \"id\":\"69e0b41a67d0068c2ca0b48e\",\n // \"name\":\"Zoho CRM\",\n // \"userId\":\"1ece66c8-feb1-4df1-b321-21607daf4623\",\n // \"tenantId\":\"69e0b3faef3e7b6248189289\",\n // \"isTest\":false,\n // \"connected\":true,\n // \"state\":\"READY\",\n // \"errors\":[],\n // \"integrationId\":\"66fe6c913202f3a165e3c14d\",\n // \"externalAppId\":\"6671653e7e2d642e4e41b0fa\",\n // \"authOptionKey\":\"\",\n // \"createdAt\":\"2026-04-16T10:04:10.420Z\",\n // \"updatedAt\":\"2026-04-16T10:04:10.575Z\",\n // \"retryAttempts\":0,\n // \"isDeactivated\":false\n // }\n\n if (connection && connection.disconnected !== true && connection.connected !== false) {\n console.log('[IntegrationApp] connection condition matched');\n try {\n const saveRequest = await axios.post(\n \"/api/v1/integration-app-connect\",\n );\n if (saveRequest.data && saveRequest.data.success === true) {\n /** If all is good refresh the page here */\n window.location = \"/dashboard\";\n return;\n }\n\n throw new Error(saveRequest.data.message);\n } catch (error) {\n console.log(error);\n showSnackbarError(normalizeError(error));\n }\n }\n },\n },\n};\n</script>\n\n<style module lang=\"less\" src=\"./connect.less\"></style>","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6089929419086115132
|
-8178086448081891036
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Code changed:
Hide
Sync Changes
Hide This Notification
33
2
19
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use HubSpot\Client\Crm\Deals\Model\CollectionResponseAssociatedId;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\Account;
use Exception;
use Jiminny\Component\DealInsights\Forecast\Forecast;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Contact;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Exceptions\CrmException;
use Jiminny\Models\Opportunity;
use Illuminate\Support\Collection;
use Jiminny\Models\Stage;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Services\Crm\Hubspot\DealFieldsService;
use Jiminny\Services\Crm\Hubspot\OpportunitySyncStrategy\HubspotSingleSyncStrategy;
use Jiminny\Services\Crm\Hubspot\WebhookSyncBatchProcessor;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Utils\CurrencyFormatter;
/**
* Optimized sync methods for better performance
* These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains
*/
trait OpportunitySyncTrait
{
private const int BATCH_SIZE = 100;
private const int BATCH_PROCESS_SIZE = 800;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected DealFieldsService $dealFieldsService;
private ?array $cachedClosedDealStages = null;
private array $cachedBusinessProcesses = [];
private array $cachedStages = [];
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$parameters['config'] = $this->config;
$syncCount = 0;
$reportedTotal = 0;
$lastSyncedId = [];
try {
foreach ($strategies as $strategyName => $syncStrategy) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .
$strategyName
);
$total = 0;
$lastId = null;
$buffer = [];
// HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies
foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {
$buffer[] = $hsOpportunity;
// process every 800 rows (fits < 1 000 association limit)
if (\count($buffer) >= self::BATCH_PROCESS_SIZE) {
$syncCount += $this->processOpportunityBatch($buffer);
$buffer = [];
}
}
// leftovers
if ($buffer) {
$syncCount += $this->processOpportunityBatch($buffer);
}
$reportedTotal += $total;
$lastSyncedId = $lastId;
}
} catch (\HubSpot\Client\Crm\Deals\ApiException | CrmException $e) {
$this->handleSyncException($e, $parameters);
}
$this->logger->info(
'[HubSpot] Synced opportunities',
[
'team' => $this->team->getId(),
'sync_count' => $syncCount,
'total' => $reportedTotal,
'last_synced_id' => $lastSyncedId,
]
);
return $reportedTotal;
}
private function handleSyncException(\Throwable $e, array $parameters): void
{
if (($parameters['since'] ?? null) instanceof Carbon) {
$parameters['since'] = $parameters['since']->toDateTimeString();
}
$parameters['config'] = $this->config->getId();
$this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [
'teamId' => $this->team->getUuid(),
'parameters' => $parameters,
'reason' => $e->getMessage(),
]);
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,
);
$parameters = [
'config' => $this->config,
'crm_id' => $crmId,
];
try {
if (! $strategy instanceof HubspotSingleSyncStrategy) {
throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');
}
$hsOpportunity = $strategy->fetchOpportunity($parameters);
} catch (\HubSpot\Client\Crm\Deals\ApiException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->getUuid(),
'crmId' => $crmId,
'reason' => $e->getMessage(),
]);
return null;
}
$hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);
return $this->importOrUpdateOpportunity($hsOpportunity);
}
/**
* Process webhook-collected opportunity batches.
*
* Drains Redis sets containing company CRM IDs collected from webhook events
* and dispatches ImportOpportunityBatch jobs for batch processing.
*
* @return int Number of opportunity IDs dispatched to jobs
*/
public function batchSyncOpportunities(): int
{
$configId = $this->team->getCrmConfiguration()->getId();
return $this->batchProcessor->processBatchesForObjectType(
WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,
$configId
);
}
/**
* Import a batch of opportunities by their CRM IDs.
* Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().
*
* @param array<string> $crmIds HubSpot deal CRM IDs
*
* @return array{success: array, failed_ids: array, errors?: array<string, string>}
*/
public function importOpportunityBatchByIds(array $crmIds): array
{
$fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);
$allDeals = [];
foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {
$deals = $this->client->getOpportunitiesByIds($chunk, $fields);
foreach ($deals as $deal) {
$allDeals[] = $deal;
}
}
// IDs not returned by HubSpot are likely deleted or inaccessible deals.
// These are not failures — retrying won't bring them back.
$fetchedIds = array_map('strval', array_column($allDeals, 'id'));
$notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));
if (! empty($notFoundIds)) {
$this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [
'teamId' => $this->team->getId(),
'notFoundCount' => \count($notFoundIds),
'notFoundIds' => $notFoundIds,
'requestedCount' => \count($crmIds),
'fetchedCount' => \count($allDeals),
]);
}
if (empty($allDeals)) {
return ['success' => [], 'failed_ids' => []];
}
return $this->importOpportunityBatch($allDeals);
}
private function getClosedDealStages(): array
{
if ($this->cachedClosedDealStages !== null) {
return $this->cachedClosedDealStages;
}
$stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);
$data = [
'lost' => [],
'won' => [],
];
foreach ($stages as $stage) {
if ($stage->probability == 0.00) {
$data['lost'][] = $stage->crm_provider_id;
}
if ($stage->probability == 100.00) {
$data['won'][] = $stage->crm_provider_id;
}
}
$this->cachedClosedDealStages = $data;
return $data;
}
/**
* Import deals into the database with pre-fetched associations.
*
* API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT
* caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()
* where Laravel retries the whole job with backoff. After all retries exhausted,
* failed() requeues all IDs to Redis.
*
* The per-deal loop catches exceptions individually. A deal can end up in three states:
* - success: imported/updated successfully
* - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)
* These are permanent issues — retrying won't fix them.
* - skipped (null): missing dependencies (no account, unknown pipeline/stage).
* This is acceptable — the deal cannot be imported until those exist.
*/
private function importOpportunityBatch(array $deals): array
{
$syncedOpportunities = [
'success' => [],
'failed_ids' => [],
];
$dealIds = array_column($deals, 'id');
// Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the
// queue job retries the whole batch and eventually requeues all deal IDs back to Redis.
try {
$companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');
$contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');
$associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);
$existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(
$this->config,
array_map('strval', $dealIds)
);
$existingCrmIdSet = array_flip($existingCrmIds);
} catch (\Throwable $e) {
$this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [
'teamId' => $this->team->getId(),
'dealCount' => count($dealIds),
'error' => $e->getMessage(),
]);
throw $e;
}
foreach ($deals as $deal) {
try {
$deal['associations'] = $this->prepareAssociationsForOpportunity(
$deal['id'],
$companyAssociations,
$contactAssociations,
$associationsData
);
$syncedOpportunity = $this->importOrUpdateOpportunity(
$deal,
isset($existingCrmIdSet[(string) $deal['id']])
);
if ($syncedOpportunity) {
$syncedOpportunities['success'][] = $syncedOpportunity;
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [
'teamId' => $this->team->getId(),
'crmId' => $deal['id'],
'error' => $e->getMessage(),
]);
$syncedOpportunities['failed_ids'][] = $deal['id'];
$syncedOpportunities['errors'][$deal['id']] = $e->getMessage();
}
}
return $syncedOpportunities;
}
/**
* Prepare associated entities for opportunities with optimized batch processing
* Returns structured data with CRM ID to DB ID mappings for each opportunity
*/
private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array
{
// Step 1: Collect all unique company and contact IDs from associations
$allCompanyIds = $this->flattenAssociationIds($companyAssociations);
$allContactIds = $this->flattenAssociationIds($contactAssociations);
// Step 2: Batch sync missing entities and get CRM ID to DB ID mappings
$companyIdMappings = [];
$contactIdMappings = [];
if (! empty($allCompanyIds)) {
$companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);
}
if (! empty($allContactIds)) {
$contactIdMappings = $this->prepareAssociatedContacts($allContactIds);
}
return [
'company_id_mappings' => $companyIdMappings,
'contact_id_mappings' => $contactIdMappings,
];
}
/**
* Flatten association data to get unique IDs
*/
private function flattenAssociationIds(array $associations): array
{
$ids = [];
foreach ($associations as $dealAssociations) {
if (is_array($dealAssociations)) {
foreach ($dealAssociations as $id) {
$ids[$id] = true;
}
}
}
return array_keys($ids);
}
/**
* Batch sync missing accounts
*/
private function prepareAssociatedAccounts(array $companyIds): array
{
// Find which accounts already exist
$existingAccounts = $this->crmEntityRepository
->findAccountsByExternalIds($this->config, $companyIds);
$existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();
$existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {
return [$account->getCrmProviderId() => $account->getId()];
})->toArray();
$missingCompanyIds = array_diff($companyIds, $existingCompanyIds);
if (empty($missingCompanyIds)) {
return $existingAccountsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [
'teamId' => $this->team->getUuid(),
'total_companies' => count($companyIds),
'existing_companies' => count($existingCompanyIds),
'missing_companies' => count($missingCompanyIds),
]);
// we already have limit on opportunity ids count
// Initialize variable before try block
$syncedAccountsData = [];
try {
$syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [
'size' => count($missingCompanyIds),
'error' => $e->getMessage(),
]);
$syncedAccountsData = [];
}
return $existingAccountsData + $syncedAccountsData;
}
/**
* Prepare associated contacts - find existing and sync missing ones
* Returns mapping of CRM ID to DB ID
*/
private function prepareAssociatedContacts(array $contactIds): array
{
// Find which contacts already exist
$existingContacts = $this->crmEntityRepository
->findContactsByExternalIds($this->config, $contactIds);
$existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();
// Create mapping for existing contacts
$existingContactsData = $existingContacts->mapWithKeys(function ($contact) {
return [$contact->getCrmProviderId() => $contact->getId()];
})->toArray();
$missingContactIds = array_diff($contactIds, $existingContactIds);
if (empty($missingContactIds)) {
return $existingContactsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [
'teamId' => $this->team->getUuid(),
'total_contacts' => count($contactIds),
'existing_contacts' => count($existingContactIds),
'missing_contacts' => count($missingContactIds),
]);
// Sync missing contacts using batch API
try {
$syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [
'size' => count($missingContactIds),
'error' => $e->getMessage(),
]);
$syncedContactsData = [];
}
return $existingContactsData + $syncedContactsData;
}
private function batchSyncCrmObjects(string $objectType, array $crmIds): array
{
$syncObjects = [];
$crmObjectIds = array_values($crmIds);
foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {
try {
$objects = $objectType === 'companies' ?
$this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :
$this->client->getContactsByIds($chunk, $this->getContactFields());
foreach ($objects as $objectId => $objectData) {
$this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [
'requested_count' => count($chunk),
'synced_count' => count($objects),
]);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [
'ids' => $chunk,
'error' => $e->getMessage(),
]);
}
}
return $syncObjects;
}
private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void
{
try {
$object = $objectType === 'companies' ?
$this->importAccount($objectData) :
$this->importContact($objectData);
if ($object) {
$syncObjects[$object->getCrmProviderId()] = $object->getId();
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [
'id' => $objectId,
'error' => $e->getMessage(),
]);
}
}
/**
* Prepare associations for a single opportunity
*
* The return value is an array with the following structure:
* [
* 'companies' => [
* $companyCrmId => $companyId,
* ...
* ],
* 'contacts' => [
* $contactCrmId => $contactId,
* ...
* ],
* 'account_id' => $accountId,
* ]
*/
private function prepareAssociationsForOpportunity(
string $oppCrmId,
array $companyAssociations,
array $contactAssociations,
array $associationsData
): array {
$associations = [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
$oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];
foreach ($oppCompanyIds as $companyCrmId) {
if (isset($associationsData['company_id_mappings'][$companyCrmId])) {
$associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];
// Set primary account (first company becomes primary account)
if ($associations['account_id'] === null) {
$associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];
}
}
}
$oppContactIds = $contactAssociations[$oppCrmId] ?? [];
foreach ($oppContactIds as $contactCrmId) {
if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {
$associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];
}
}
return $associations;
}
/**
* Update only associations for an opportunity
*/
private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void
{
// Update contact associations
$this->importOpportunityContacts($opportunity, $associations['contacts']);
// Update company (account) associations
$this->updateOpportunityAccount($opportunity, $associations['account_id']);
}
/**
* Remove all contact associations from an opportunity
*/
private function removeAllOpportunityContacts(Opportunity $opportunity): void
{
$currentCount = (int) $opportunity->contacts()->count();
if ($currentCount > 0) {
$opportunity->contacts()->detach();
$this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_count' => $currentCount,
]);
}
}
private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void
{
if ($accountId === null) {
// No account ID provided - keep current account
return;
}
$currentAccountId = $opportunity->getAccountId();
// Only update if account has changed
if ($currentAccountId !== $accountId) {
$opportunity->account_id = $accountId;
$opportunity->save();
$this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [
'opportunity_id' => $opportunity->getId(),
'old_account_id' => $currentAccountId,
'new_account_id' => $accountId,
]);
}
}
/**
* Find existing opportunities by external IDs (OPTIMIZED VERSION)
* Uses batch query for better performance
*/
private function findExistingOpportunities(array $crmIds): Collection
{
return $this->crmEntityRepository
->findOpportunitiesByExternalIds($this->config, $crmIds);
}
private function processOpportunityBatch(array $opportunities): int
{
$syncedOpportunities = $this->importOpportunityBatch($opportunities);
return count($syncedOpportunities['success'] ?? []);
}
/**
* Convert single deal associations from HubSpot format to internal format
* Handles both HubSpot SDK objects and array formats
*
* @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed
*
* @return array Processed associations with DB IDs
*/
private function convertDealAssociations(array $opportunityAssociations): array
{
$associations = $this->initializeAssociationsStructure();
if (empty($opportunityAssociations)) {
return $associations;
}
$associationIds = $this->extractAssociationIds($opportunityAssociations);
$this->processCompanyAssociations($associationIds, $associations);
$this->processContactAssociations($associationIds, $associations);
return $associations;
}
private function initializeAssociationsStructure(): array
{
return [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
}
private function extractAssociationIds(array $opportunityAssociations): array
{
$associationIds = [];
foreach ($opportunityAssociations as $type => $associationData) {
if (! empty($associationData)) {
$associationIds[$type] = $this->convertSingleDealAssociations($associationData);
}
}
return $associationIds;
}
private function processCompanyAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['companies'])) {
return;
}
$companyId = $associationIds['companies'][0];
$account = $this->findOrSyncAccount($companyId);
if ($account instanceof Account) {
$associations['companies'][$companyId] = $account->getId();
$associations['account_id'] = $account->getId();
}
}
private function processContactAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['contacts'])) {
return;
}
foreach ($associationIds['contacts'] as $contactId) {
$contact = $this->findOrSyncContact($contactId);
if ($contact instanceof Contact) {
$associations['contacts'][$contactId] = $contact->getId();
}
}
}
private function findOrSyncAccount(string $companyId): ?Account
{
$account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);
if (! $account instanceof Account) {
$account = $this->syncAccount($companyId);
}
return $account;
}
private function findOrSyncContact(string $contactId): ?Contact
{
$contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);
if (! $contact instanceof Contact) {
$contact = $this->syncContact($contactId);
}
return $contact;
}
private function convertSingleDealAssociations($opportunityAssociations = null): array
{
$associationData = [];
if ($opportunityAssociations === null) {
return $associationData;
}
// Handle array input (from extractAssociationIds)
if (is_array($opportunityAssociations)) {
return $opportunityAssociations;
}
// Handle CollectionResponseAssociatedId object
if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {
foreach ($opportunityAssociations->getResults() as $association) {
$associationData[] = $association->getId();
}
}
return $associationData;
}
private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity
{
if (empty($crmData['properties'])) {
return null;
}
$crmId = (string) $crmData['id'];
$properties = $crmData['properties'];
$associations = $crmData['associations'] ?? [];
$opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(
$this->config,
$crmId
);
if ($opportunityExists) {
return $this->updateOpportunity($crmId, $properties, $associations);
} else {
return $this->createOpportunity($crmId, $properties, $associations);
}
}
/**
* Create new opportunity
*/
private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity
{
$accountId = $this->resolveAccountId($associations);
if (! $accountId) {
return null;
}
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
if (! $businessProcess) {
return null;
}
$stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);
if (! $stage) {
return null;
}
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->importOpportunityContacts($opportunity, $associations['contacts']);
if ($opportunity->wasRecentlyCreated) {
MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());
}
return $opportunity;
}
/**
* Update existing opportunity
*/
private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity
{
$accountId = $this->resolveAccountId($associations);
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
$stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->updateOpportunityAssociations($opportunity, $associations);
return $opportunity;
}
private function resolveAccountId(array $associations): ?int
{
if (! empty($associations['accountId'])) {
return $associations['accountId'];
}
if (empty($associations)) {
return null;
}
// we can't resolve multiple account ids (currently SDK returns one company)
foreach ($associations['companies'] as $accountId) {
return $accountId;
}
return null;
}
private function buildOpportunityData(
array $properties,
?int $accountId,
?BusinessProcess $businessProcess,
?Stage $stage
): array {
$ownerId = null;
$profile = null;
if (! empty($properties['hubspot_owner_id'])) {
$ownerId = $properties['hubspot_owner_id'];
$profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);
}
$name = 'Unknown';
if (isset($properties['dealname'])) {
$name = mb_strimwidth($properties['dealname'], 0, 128);
}
$amount = $this->resolveAmount($properties);
$currency = $properties['deal_currency_code'] ?? null;
$closeDate = null;
if (! empty($properties['closedate'])) {
$closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');
}
$remotelyCreatedAt = null;
if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {
$date = $this->parseCleanDatetime($properties['createdate']);
$remotelyCreatedAt = $date?->format('Y-m-d H:i:s');
}
$closedStages = $this->getClosedDealStages();
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$data = [
'team_id' => $this->team->getId(),
'user_id' => $profile ? $profile->user_id : null,
'owner_id' => $ownerId,
'name' => $name,
'value' => ! empty($amount) ? $amount : null,
'currency_code' => CurrencyFormatter::formatCode($currency),
'close_date' => $closeDate,
'is_closed' => $isWon || $isLost,
'is_won' => $isWon,
'remotely_created_at' => $remotelyCreatedAt,
'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),
'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),
];
if ($accountId) {
$data['account_id'] = $accountId;
}
if ($stage) {
$data['stage_id'] = $stage->id;
}
if ($businessProcess) {
$recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);
if ($recordType) {
$data['record_type_id'] = $recordType->id;
}
}
return $data;
}
private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess
{
if ($pipelineId === null) {
return null;
}
if (isset($this->cachedBusinessProcesses[$pipelineId])) {
return $this->cachedBusinessProcesses[$pipelineId];
}
$businessProcess = $this->getBusinessProcess($pipelineId);
if (! $businessProcess instanceof BusinessProcess) {
$this->importStages();
$businessProcess = $this->getBusinessProcess($pipelineId);
}
if (! $businessProcess instanceof BusinessProcess) {
$this->logger->info(
'[HubSpot] Deal is not attached to a pipeline',
[
'pipeline' => $pipelineId]
);
}
$this->cachedBusinessProcesses[$pipelineId] = $businessProcess;
return $businessProcess;
}
private function getBusinessProcess(string $pipelineId): ?BusinessProcess
{
return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);
}
private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage
{
if (empty($stageId)) {
return null;
}
$cacheKey = $businessProcess->getId() . ':' . $stageId;
if (isset($this->cachedStages[$cacheKey])) {
return $this->cachedStages[$cacheKey];
}
$stage = $this->crmEntityRepository->getPipelineStageByConditions(
$businessProcess,
[
'crm_provider_id' => $stageId,
'type' => Stage::TYPE_OPPORTUNITY,
]
);
if ($stage === null) {
$this->importStages(null, $stageId);
}
if ($stage === null) {
$this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);
}
$this->cachedStages[$cacheKey] = $stage;
return $stage;
}
private function resolveAmount(array $properties): ?string
{
$amount = null;
if (! empty($properties['amount'])) {
$amount = str_replace(',', '', $properties['amount']);
}
if ($this->config->hasDefaultCurrencyFieldSet()) {
$valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();
$amount = $properties[$valueFieldName] ?? $amount;
}
return $amount;
}
private function parseCleanDatetime(string $datetime): ?Carbon
{
// Treat pre-1980 values as invalid
$minValidDate = Carbon::parse('1980-01-01 00:00:00');
try {
$date = Carbon::parse($datetime);
if ($minValidDate->gt($date)) {
return null;
}
return $date;
} catch (Exception) {
return null; // On parse error, treat as null
}
}
private function resolveDealProbability(?string $stageProbability): int
{
if ($stageProbability === null) {
return 0;
}
$probability = (float) $stageProbability;
return $probability > 1 ? 0 : (int) ($probability * 100);
}
private function resolveForecastCategory(?string $forecastCategory): string
{
if (! $forecastCategory) {
return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;
}
$forecastCategory = str_replace('_', ' ', $forecastCategory);
return ucwords(strtolower($forecastCategory));
}
private function importExternalFieldData(array $properties, int $opportunityId): void
{
$crmFields = $this->getOpportunitySyncableFields();
$this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);
}
private function importOpportunityContacts(Opportunity $opportunity, array $associations): void
{
// Handle empty or missing contact associations
if (empty($associations)) {
// Remove all existing contact associations if none provided
$this->removeAllOpportunityContacts($opportunity);
return;
}
// Use differential sync approach for better performance and accuracy
$this->syncOpportunityContactsDifferential($opportunity, $associations);
}
/**
* Sync opportunity contacts using differential approach
* This compares current vs new associations and only makes necessary changes
*/
private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void
{
$currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);
$contactAssociationIds = array_keys($contactAssociations);
$contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);
$contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);
if (empty($contactsToAdd) && empty($contactsToRemove)) {
return;
}
$this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);
$this->removeContactAssociations($opportunity, $contactsToRemove);
$this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);
}
private function getCurrentContactCrmIds(Opportunity $opportunity): array
{
return $opportunity->contacts()
->pluck('contacts.crm_provider_id')
->toArray();
}
private function logContactAssociationChanges(
Opportunity $opportunity,
array $currentContactCrmIds,
array $contactAssociations,
array $contactsToAdd,
array $contactsToRemove
): void {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [
'opportunity_id' => $opportunity->getId(),
'current_contacts' => $currentContactCrmIds,
'new_contacts' => $contactAssociations,
'contacts_to_add' => $contactsToAdd,
'contacts_to_remove' => $contactsToRemove,
]);
}
private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void
{
if (empty($contactsToRemove)) {
return;
}
$contactsToDetach = $opportunity->contacts()
->whereIn('contacts.crm_provider_id', $contactsToRemove)
->pluck('contacts.id')
->toArray();
if (! empty($contactsToDetach)) {
$opportunity->contacts()->detach($contactsToDetach);
$this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_contact_crm_ids' => $contactsToRemove,
'removed_contact_count' => count($contactsToDetach),
]);
}
}
private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void
{
if (empty($contactsToAdd)) {
return;
}
$contactsAdded = [];
foreach ($contactsToAdd as $crmId) {
$id = $contactAssociations[$crmId];
if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {
$contactsAdded[] = $crmId;
}
}
$this->logAddedContacts($opportunity, $contactsAdded);
}
private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool
{
try {
$contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);
if (! $contact) {
return false;
}
return $this->performContactAttachment($opportunity, $contact, $crmId);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [
'opportunity_id' => $opportunity->getId(),
'contact_crm_id' => $crmId,
'error' => $e->getMessage(),
]);
return false;
}
}
private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool
{
try {
$opportunity->contacts()->attach($contact->getId(), [
'crm_provider_id' => $crmId,
]);
return true;
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [
'contact_id' => $contact->getId(),
'contact_crm_id' => $crmId,
'opportunity_id' => $opportunity->getId(),
]);
return false;
}
throw $e;
}
}
private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void
{
if (! empty($contactsAdded)) {
$this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [
'opportunity_id' => $opportunity->getId(),
'contacts_to_add_count' => count($contactsAdded),
'added_contact_crm_ids' => $contactsAdded,
'added_contacts_count' => count($contactsAdded),
]);
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<template>
<WelcomeLayout
title="Account disconnected"
textPosition="center"
:icon="faUnlink"
:class="$style.layout"
>
<div :class="$style.container" v-if="providersLoaded">
<p>
<strong>
It looks like your {{ localProvider.displayName }} account has become
disconnected
</strong>
</p>
<p :class="$style.small">Please re-connect to continue</p>
<p v-if="isInIframe">
We'll open the {{ localProvider.displayName }} authentication in a new
tab. Please return here and refresh the page once complete
</p>
<GoogleLikeButton
v-if="localProvider.viaIntegrationApp && crmTokenLoaded"
as="a"
:key="localProvider.name"
:brand-logo="localProvider.name"
:class="$style.connectButton"
@click="integrationAppOnClick"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
<GoogleLikeButton
v-if="!localProvider.viaIntegrationApp"
as="a"
:key="localProvider.name"
:href="`/auth/redirect/${localProvider.name}`"
:target="target"
:brand-logo="localProvider.name"
:class="$style.connectButton"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
</div>
<BuildInfo />
<KioskBanner />
</WelcomeLayout>
</template>
<script>
import window from "window";
import axios from "axios";
import { faUnlink } from "@fortawesome/pro-regular-svg-icons";
import isInIframe from "@/utils/isInIframe";
import BuildInfo from "@/components/layout/BuildInfo/BuildInfo.vue";
import KioskBanner from "@/components/shared/KioskBanner/KioskBanner.vue";
import WelcomeLayout from "@/components/layout/WelcomeLayout/WelcomeLayout.vue";
import GoogleLikeButton from "@/components/shared/Buttons/GoogleLikeButton.vue";
import { showSnackbarError, normalizeError } from "@/utils/index";
import { IntegrationAppClient } from "@integration-app/sdk";
export default {
name: "ConnectPage",
components: {
BuildInfo,
KioskBanner,
WelcomeLayout,
GoogleLikeButton,
},
data() {
return {
...window.connectData,
crmToken: null,
faUnlink,
isInIframe,
providers: [],
providersLoaded: false,
crmTokenLoaded: false,
};
},
computed: {
localProvider() {
return this.providers.find((e) => e.name === this.provider);
},
target() {
return this.isInIframe ? "_blank" : null;
},
},
created() {
this.getProviders();
},
mounted() {
this.showErrors();
},
watch: {
providersLoaded() {
if (this.providersLoaded) {
this.prepareIntegrationAppConnection();
}
},
},
methods: {
showErrors() {
if (!this.error) return;
showSnackbarError(this.error, undefined, undefined, false);
},
unwrapEntityResponse({ data }) {
return data.map(({ icon, name, displayName, viaIntegrationApp }) => {
return { icon, name, displayName, viaIntegrationApp };
});
},
async getProviders() {
try {
const response = await axios.get("/api/v1/connect-providers");
this.providers = this.unwrapEntityResponse(response);
this.providersLoaded = true;
} catch {
showSnackbarError(
"An error occurred, while loading form data (connect providers).",
);
}
},
async prepareIntegrationAppConnection() {
if (this.localProvider.viaIntegrationApp) {
try {
const response = await axios.get("/api/v1/integration-app-token");
this.crmToken = response.data.token;
this.crmTokenLoaded = true;
} catch (error) {
console.log(error);
showSnackbarError(
`An error occurred while preparing the page.
Try refreshing, if the error persists get in touch with the Jiminny team.`,
);
}
}
},
async integrationAppOnClick() {
const integrationApp = new IntegrationAppClient({
token: this.crmToken,
});
const connection = await integrationApp
.integration(this.localProvider.name)
.openNewConnection({
showPoweredBy: false,
allowMultipleConnections: false,
});
console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));
// [IntegrationApp] openNewConnection resolved: {
// "id":"69e0b41a67d0068c2ca0b48e",
// "name":"Zoho CRM",
// "userId":"1ece66c8-feb1-4df1-b321-21607daf4623",
// "tenantId":"69e0b3faef3e7b6248189289",
// "isTest":false,
// "connected":true,
// "state":"READY",
// "errors":[],
// "integrationId":"66fe6c913202f3a165e3c14d",
// "externalAppId":"6671653e7e2d642e4e41b0fa",
// "authOptionKey":"",
// "createdAt":"2026-04-16T10:04:10.420Z",
// "updatedAt":"2026-04-16T10:04:10.575Z",
// "retryAttempts":0,
// "isDeactivated":false
// }
if (connection && connection.disconnected !== true && connection.connected !== false) {
console.log('[IntegrationApp] connection condition matched');
try {
const saveRequest = await axios.post(
"/api/v1/integration-app-connect",
);
if (saveRequest.data && saveRequest.data.success === true) {
/** If all is good refresh the page here */
window.location = "/dashboard";
return;
}
throw new Error(saveRequest.data.message);
} catch (error) {
console.log(error);
showSnackbarError(normalizeError(error));
}
}
},
},
};
</script>
<style module lang="less" src="./connect.less"></style>
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
46362
|
|
46367
|
980
|
0
|
2026-04-17T10:31:51.045798+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776421911045_m2.jpg...
|
PhpStorm
|
faVsco.js – ~/jiminny/app/front-end/src/components faVsco.js – ~/jiminny/app/front-end/src/components/connect/connect.vue...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Code changed:
Hide
Sync Changes
Hide This Notification
33
2
19
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use HubSpot\Client\Crm\Deals\Model\CollectionResponseAssociatedId;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\Account;
use Exception;
use Jiminny\Component\DealInsights\Forecast\Forecast;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Contact;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Exceptions\CrmException;
use Jiminny\Models\Opportunity;
use Illuminate\Support\Collection;
use Jiminny\Models\Stage;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Services\Crm\Hubspot\DealFieldsService;
use Jiminny\Services\Crm\Hubspot\OpportunitySyncStrategy\HubspotSingleSyncStrategy;
use Jiminny\Services\Crm\Hubspot\WebhookSyncBatchProcessor;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Utils\CurrencyFormatter;
/**
* Optimized sync methods for better performance
* These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains
*/
trait OpportunitySyncTrait
{
private const int BATCH_SIZE = 100;
private const int BATCH_PROCESS_SIZE = 800;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected DealFieldsService $dealFieldsService;
private ?array $cachedClosedDealStages = null;
private array $cachedBusinessProcesses = [];
private array $cachedStages = [];
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$parameters['config'] = $this->config;
$syncCount = 0;
$reportedTotal = 0;
$lastSyncedId = [];
try {
foreach ($strategies as $strategyName => $syncStrategy) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .
$strategyName
);
$total = 0;
$lastId = null;
$buffer = [];
// HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies
foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {
$buffer[] = $hsOpportunity;
// process every 800 rows (fits < 1 000 association limit)
if (\count($buffer) >= self::BATCH_PROCESS_SIZE) {
$syncCount += $this->processOpportunityBatch($buffer);
$buffer = [];
}
}
// leftovers
if ($buffer) {
$syncCount += $this->processOpportunityBatch($buffer);
}
$reportedTotal += $total;
$lastSyncedId = $lastId;
}
} catch (\HubSpot\Client\Crm\Deals\ApiException | CrmException $e) {
$this->handleSyncException($e, $parameters);
}
$this->logger->info(
'[HubSpot] Synced opportunities',
[
'team' => $this->team->getId(),
'sync_count' => $syncCount,
'total' => $reportedTotal,
'last_synced_id' => $lastSyncedId,
]
);
return $reportedTotal;
}
private function handleSyncException(\Throwable $e, array $parameters): void
{
if (($parameters['since'] ?? null) instanceof Carbon) {
$parameters['since'] = $parameters['since']->toDateTimeString();
}
$parameters['config'] = $this->config->getId();
$this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [
'teamId' => $this->team->getUuid(),
'parameters' => $parameters,
'reason' => $e->getMessage(),
]);
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,
);
$parameters = [
'config' => $this->config,
'crm_id' => $crmId,
];
try {
if (! $strategy instanceof HubspotSingleSyncStrategy) {
throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');
}
$hsOpportunity = $strategy->fetchOpportunity($parameters);
} catch (\HubSpot\Client\Crm\Deals\ApiException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->getUuid(),
'crmId' => $crmId,
'reason' => $e->getMessage(),
]);
return null;
}
$hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);
return $this->importOrUpdateOpportunity($hsOpportunity);
}
/**
* Process webhook-collected opportunity batches.
*
* Drains Redis sets containing company CRM IDs collected from webhook events
* and dispatches ImportOpportunityBatch jobs for batch processing.
*
* @return int Number of opportunity IDs dispatched to jobs
*/
public function batchSyncOpportunities(): int
{
$configId = $this->team->getCrmConfiguration()->getId();
return $this->batchProcessor->processBatchesForObjectType(
WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,
$configId
);
}
/**
* Import a batch of opportunities by their CRM IDs.
* Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().
*
* @param array<string> $crmIds HubSpot deal CRM IDs
*
* @return array{success: array, failed_ids: array, errors?: array<string, string>}
*/
public function importOpportunityBatchByIds(array $crmIds): array
{
$fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);
$allDeals = [];
foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {
$deals = $this->client->getOpportunitiesByIds($chunk, $fields);
foreach ($deals as $deal) {
$allDeals[] = $deal;
}
}
// IDs not returned by HubSpot are likely deleted or inaccessible deals.
// These are not failures — retrying won't bring them back.
$fetchedIds = array_map('strval', array_column($allDeals, 'id'));
$notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));
if (! empty($notFoundIds)) {
$this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [
'teamId' => $this->team->getId(),
'notFoundCount' => \count($notFoundIds),
'notFoundIds' => $notFoundIds,
'requestedCount' => \count($crmIds),
'fetchedCount' => \count($allDeals),
]);
}
if (empty($allDeals)) {
return ['success' => [], 'failed_ids' => []];
}
return $this->importOpportunityBatch($allDeals);
}
private function getClosedDealStages(): array
{
if ($this->cachedClosedDealStages !== null) {
return $this->cachedClosedDealStages;
}
$stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);
$data = [
'lost' => [],
'won' => [],
];
foreach ($stages as $stage) {
if ($stage->probability == 0.00) {
$data['lost'][] = $stage->crm_provider_id;
}
if ($stage->probability == 100.00) {
$data['won'][] = $stage->crm_provider_id;
}
}
$this->cachedClosedDealStages = $data;
return $data;
}
/**
* Import deals into the database with pre-fetched associations.
*
* API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT
* caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()
* where Laravel retries the whole job with backoff. After all retries exhausted,
* failed() requeues all IDs to Redis.
*
* The per-deal loop catches exceptions individually. A deal can end up in three states:
* - success: imported/updated successfully
* - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)
* These are permanent issues — retrying won't fix them.
* - skipped (null): missing dependencies (no account, unknown pipeline/stage).
* This is acceptable — the deal cannot be imported until those exist.
*/
private function importOpportunityBatch(array $deals): array
{
$syncedOpportunities = [
'success' => [],
'failed_ids' => [],
];
$dealIds = array_column($deals, 'id');
// Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the
// queue job retries the whole batch and eventually requeues all deal IDs back to Redis.
try {
$companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');
$contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');
$associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);
$existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(
$this->config,
array_map('strval', $dealIds)
);
$existingCrmIdSet = array_flip($existingCrmIds);
} catch (\Throwable $e) {
$this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [
'teamId' => $this->team->getId(),
'dealCount' => count($dealIds),
'error' => $e->getMessage(),
]);
throw $e;
}
foreach ($deals as $deal) {
try {
$deal['associations'] = $this->prepareAssociationsForOpportunity(
$deal['id'],
$companyAssociations,
$contactAssociations,
$associationsData
);
$syncedOpportunity = $this->importOrUpdateOpportunity(
$deal,
isset($existingCrmIdSet[(string) $deal['id']])
);
if ($syncedOpportunity) {
$syncedOpportunities['success'][] = $syncedOpportunity;
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [
'teamId' => $this->team->getId(),
'crmId' => $deal['id'],
'error' => $e->getMessage(),
]);
$syncedOpportunities['failed_ids'][] = $deal['id'];
$syncedOpportunities['errors'][$deal['id']] = $e->getMessage();
}
}
return $syncedOpportunities;
}
/**
* Prepare associated entities for opportunities with optimized batch processing
* Returns structured data with CRM ID to DB ID mappings for each opportunity
*/
private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array
{
// Step 1: Collect all unique company and contact IDs from associations
$allCompanyIds = $this->flattenAssociationIds($companyAssociations);
$allContactIds = $this->flattenAssociationIds($contactAssociations);
// Step 2: Batch sync missing entities and get CRM ID to DB ID mappings
$companyIdMappings = [];
$contactIdMappings = [];
if (! empty($allCompanyIds)) {
$companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);
}
if (! empty($allContactIds)) {
$contactIdMappings = $this->prepareAssociatedContacts($allContactIds);
}
return [
'company_id_mappings' => $companyIdMappings,
'contact_id_mappings' => $contactIdMappings,
];
}
/**
* Flatten association data to get unique IDs
*/
private function flattenAssociationIds(array $associations): array
{
$ids = [];
foreach ($associations as $dealAssociations) {
if (is_array($dealAssociations)) {
foreach ($dealAssociations as $id) {
$ids[$id] = true;
}
}
}
return array_keys($ids);
}
/**
* Batch sync missing accounts
*/
private function prepareAssociatedAccounts(array $companyIds): array
{
// Find which accounts already exist
$existingAccounts = $this->crmEntityRepository
->findAccountsByExternalIds($this->config, $companyIds);
$existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();
$existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {
return [$account->getCrmProviderId() => $account->getId()];
})->toArray();
$missingCompanyIds = array_diff($companyIds, $existingCompanyIds);
if (empty($missingCompanyIds)) {
return $existingAccountsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [
'teamId' => $this->team->getUuid(),
'total_companies' => count($companyIds),
'existing_companies' => count($existingCompanyIds),
'missing_companies' => count($missingCompanyIds),
]);
// we already have limit on opportunity ids count
// Initialize variable before try block
$syncedAccountsData = [];
try {
$syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [
'size' => count($missingCompanyIds),
'error' => $e->getMessage(),
]);
$syncedAccountsData = [];
}
return $existingAccountsData + $syncedAccountsData;
}
/**
* Prepare associated contacts - find existing and sync missing ones
* Returns mapping of CRM ID to DB ID
*/
private function prepareAssociatedContacts(array $contactIds): array
{
// Find which contacts already exist
$existingContacts = $this->crmEntityRepository
->findContactsByExternalIds($this->config, $contactIds);
$existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();
// Create mapping for existing contacts
$existingContactsData = $existingContacts->mapWithKeys(function ($contact) {
return [$contact->getCrmProviderId() => $contact->getId()];
})->toArray();
$missingContactIds = array_diff($contactIds, $existingContactIds);
if (empty($missingContactIds)) {
return $existingContactsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [
'teamId' => $this->team->getUuid(),
'total_contacts' => count($contactIds),
'existing_contacts' => count($existingContactIds),
'missing_contacts' => count($missingContactIds),
]);
// Sync missing contacts using batch API
try {
$syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [
'size' => count($missingContactIds),
'error' => $e->getMessage(),
]);
$syncedContactsData = [];
}
return $existingContactsData + $syncedContactsData;
}
private function batchSyncCrmObjects(string $objectType, array $crmIds): array
{
$syncObjects = [];
$crmObjectIds = array_values($crmIds);
foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {
try {
$objects = $objectType === 'companies' ?
$this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :
$this->client->getContactsByIds($chunk, $this->getContactFields());
foreach ($objects as $objectId => $objectData) {
$this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [
'requested_count' => count($chunk),
'synced_count' => count($objects),
]);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [
'ids' => $chunk,
'error' => $e->getMessage(),
]);
}
}
return $syncObjects;
}
private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void
{
try {
$object = $objectType === 'companies' ?
$this->importAccount($objectData) :
$this->importContact($objectData);
if ($object) {
$syncObjects[$object->getCrmProviderId()] = $object->getId();
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [
'id' => $objectId,
'error' => $e->getMessage(),
]);
}
}
/**
* Prepare associations for a single opportunity
*
* The return value is an array with the following structure:
* [
* 'companies' => [
* $companyCrmId => $companyId,
* ...
* ],
* 'contacts' => [
* $contactCrmId => $contactId,
* ...
* ],
* 'account_id' => $accountId,
* ]
*/
private function prepareAssociationsForOpportunity(
string $oppCrmId,
array $companyAssociations,
array $contactAssociations,
array $associationsData
): array {
$associations = [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
$oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];
foreach ($oppCompanyIds as $companyCrmId) {
if (isset($associationsData['company_id_mappings'][$companyCrmId])) {
$associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];
// Set primary account (first company becomes primary account)
if ($associations['account_id'] === null) {
$associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];
}
}
}
$oppContactIds = $contactAssociations[$oppCrmId] ?? [];
foreach ($oppContactIds as $contactCrmId) {
if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {
$associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];
}
}
return $associations;
}
/**
* Update only associations for an opportunity
*/
private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void
{
// Update contact associations
$this->importOpportunityContacts($opportunity, $associations['contacts']);
// Update company (account) associations
$this->updateOpportunityAccount($opportunity, $associations['account_id']);
}
/**
* Remove all contact associations from an opportunity
*/
private function removeAllOpportunityContacts(Opportunity $opportunity): void
{
$currentCount = (int) $opportunity->contacts()->count();
if ($currentCount > 0) {
$opportunity->contacts()->detach();
$this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_count' => $currentCount,
]);
}
}
private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void
{
if ($accountId === null) {
// No account ID provided - keep current account
return;
}
$currentAccountId = $opportunity->getAccountId();
// Only update if account has changed
if ($currentAccountId !== $accountId) {
$opportunity->account_id = $accountId;
$opportunity->save();
$this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [
'opportunity_id' => $opportunity->getId(),
'old_account_id' => $currentAccountId,
'new_account_id' => $accountId,
]);
}
}
/**
* Find existing opportunities by external IDs (OPTIMIZED VERSION)
* Uses batch query for better performance
*/
private function findExistingOpportunities(array $crmIds): Collection
{
return $this->crmEntityRepository
->findOpportunitiesByExternalIds($this->config, $crmIds);
}
private function processOpportunityBatch(array $opportunities): int
{
$syncedOpportunities = $this->importOpportunityBatch($opportunities);
return count($syncedOpportunities['success'] ?? []);
}
/**
* Convert single deal associations from HubSpot format to internal format
* Handles both HubSpot SDK objects and array formats
*
* @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed
*
* @return array Processed associations with DB IDs
*/
private function convertDealAssociations(array $opportunityAssociations): array
{
$associations = $this->initializeAssociationsStructure();
if (empty($opportunityAssociations)) {
return $associations;
}
$associationIds = $this->extractAssociationIds($opportunityAssociations);
$this->processCompanyAssociations($associationIds, $associations);
$this->processContactAssociations($associationIds, $associations);
return $associations;
}
private function initializeAssociationsStructure(): array
{
return [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
}
private function extractAssociationIds(array $opportunityAssociations): array
{
$associationIds = [];
foreach ($opportunityAssociations as $type => $associationData) {
if (! empty($associationData)) {
$associationIds[$type] = $this->convertSingleDealAssociations($associationData);
}
}
return $associationIds;
}
private function processCompanyAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['companies'])) {
return;
}
$companyId = $associationIds['companies'][0];
$account = $this->findOrSyncAccount($companyId);
if ($account instanceof Account) {
$associations['companies'][$companyId] = $account->getId();
$associations['account_id'] = $account->getId();
}
}
private function processContactAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['contacts'])) {
return;
}
foreach ($associationIds['contacts'] as $contactId) {
$contact = $this->findOrSyncContact($contactId);
if ($contact instanceof Contact) {
$associations['contacts'][$contactId] = $contact->getId();
}
}
}
private function findOrSyncAccount(string $companyId): ?Account
{
$account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);
if (! $account instanceof Account) {
$account = $this->syncAccount($companyId);
}
return $account;
}
private function findOrSyncContact(string $contactId): ?Contact
{
$contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);
if (! $contact instanceof Contact) {
$contact = $this->syncContact($contactId);
}
return $contact;
}
private function convertSingleDealAssociations($opportunityAssociations = null): array
{
$associationData = [];
if ($opportunityAssociations === null) {
return $associationData;
}
// Handle array input (from extractAssociationIds)
if (is_array($opportunityAssociations)) {
return $opportunityAssociations;
}
// Handle CollectionResponseAssociatedId object
if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {
foreach ($opportunityAssociations->getResults() as $association) {
$associationData[] = $association->getId();
}
}
return $associationData;
}
private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity
{
if (empty($crmData['properties'])) {
return null;
}
$crmId = (string) $crmData['id'];
$properties = $crmData['properties'];
$associations = $crmData['associations'] ?? [];
$opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(
$this->config,
$crmId
);
if ($opportunityExists) {
return $this->updateOpportunity($crmId, $properties, $associations);
} else {
return $this->createOpportunity($crmId, $properties, $associations);
}
}
/**
* Create new opportunity
*/
private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity
{
$accountId = $this->resolveAccountId($associations);
if (! $accountId) {
return null;
}
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
if (! $businessProcess) {
return null;
}
$stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);
if (! $stage) {
return null;
}
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->importOpportunityContacts($opportunity, $associations['contacts']);
if ($opportunity->wasRecentlyCreated) {
MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());
}
return $opportunity;
}
/**
* Update existing opportunity
*/
private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity
{
$accountId = $this->resolveAccountId($associations);
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
$stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->updateOpportunityAssociations($opportunity, $associations);
return $opportunity;
}
private function resolveAccountId(array $associations): ?int
{
if (! empty($associations['accountId'])) {
return $associations['accountId'];
}
if (empty($associations)) {
return null;
}
// we can't resolve multiple account ids (currently SDK returns one company)
foreach ($associations['companies'] as $accountId) {
return $accountId;
}
return null;
}
private function buildOpportunityData(
array $properties,
?int $accountId,
?BusinessProcess $businessProcess,
?Stage $stage
): array {
$ownerId = null;
$profile = null;
if (! empty($properties['hubspot_owner_id'])) {
$ownerId = $properties['hubspot_owner_id'];
$profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);
}
$name = 'Unknown';
if (isset($properties['dealname'])) {
$name = mb_strimwidth($properties['dealname'], 0, 128);
}
$amount = $this->resolveAmount($properties);
$currency = $properties['deal_currency_code'] ?? null;
$closeDate = null;
if (! empty($properties['closedate'])) {
$closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');
}
$remotelyCreatedAt = null;
if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {
$date = $this->parseCleanDatetime($properties['createdate']);
$remotelyCreatedAt = $date?->format('Y-m-d H:i:s');
}
$closedStages = $this->getClosedDealStages();
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$data = [
'team_id' => $this->team->getId(),
'user_id' => $profile ? $profile->user_id : null,
'owner_id' => $ownerId,
'name' => $name,
'value' => ! empty($amount) ? $amount : null,
'currency_code' => CurrencyFormatter::formatCode($currency),
'close_date' => $closeDate,
'is_closed' => $isWon || $isLost,
'is_won' => $isWon,
'remotely_created_at' => $remotelyCreatedAt,
'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),
'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),
];
if ($accountId) {
$data['account_id'] = $accountId;
}
if ($stage) {
$data['stage_id'] = $stage->id;
}
if ($businessProcess) {
$recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);
if ($recordType) {
$data['record_type_id'] = $recordType->id;
}
}
return $data;
}
private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess
{
if ($pipelineId === null) {
return null;
}
if (isset($this->cachedBusinessProcesses[$pipelineId])) {
return $this->cachedBusinessProcesses[$pipelineId];
}
$businessProcess = $this->getBusinessProcess($pipelineId);
if (! $businessProcess instanceof BusinessProcess) {
$this->importStages();
$businessProcess = $this->getBusinessProcess($pipelineId);
}
if (! $businessProcess instanceof BusinessProcess) {
$this->logger->info(
'[HubSpot] Deal is not attached to a pipeline',
[
'pipeline' => $pipelineId]
);
}
$this->cachedBusinessProcesses[$pipelineId] = $businessProcess;
return $businessProcess;
}
private function getBusinessProcess(string $pipelineId): ?BusinessProcess
{
return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);
}
private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage
{
if (empty($stageId)) {
return null;
}
$cacheKey = $businessProcess->getId() . ':' . $stageId;
if (isset($this->cachedStages[$cacheKey])) {
return $this->cachedStages[$cacheKey];
}
$stage = $this->crmEntityRepository->getPipelineStageByConditions(
$businessProcess,
[
'crm_provider_id' => $stageId,
'type' => Stage::TYPE_OPPORTUNITY,
]
);
if ($stage === null) {
$this->importStages(null, $stageId);
}
if ($stage === null) {
$this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);
}
$this->cachedStages[$cacheKey] = $stage;
return $stage;
}
private function resolveAmount(array $properties): ?string
{
$amount = null;
if (! empty($properties['amount'])) {
$amount = str_replace(',', '', $properties['amount']);
}
if ($this->config->hasDefaultCurrencyFieldSet()) {
$valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();
$amount = $properties[$valueFieldName] ?? $amount;
}
return $amount;
}
private function parseCleanDatetime(string $datetime): ?Carbon
{
// Treat pre-1980 values as invalid
$minValidDate = Carbon::parse('1980-01-01 00:00:00');
try {
$date = Carbon::parse($datetime);
if ($minValidDate->gt($date)) {
return null;
}
return $date;
} catch (Exception) {
return null; // On parse error, treat as null
}
}
private function resolveDealProbability(?string $stageProbability): int
{
if ($stageProbability === null) {
return 0;
}
$probability = (float) $stageProbability;
return $probability > 1 ? 0 : (int) ($probability * 100);
}
private function resolveForecastCategory(?string $forecastCategory): string
{
if (! $forecastCategory) {
return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;
}
$forecastCategory = str_replace('_', ' ', $forecastCategory);
return ucwords(strtolower($forecastCategory));
}
private function importExternalFieldData(array $properties, int $opportunityId): void
{
$crmFields = $this->getOpportunitySyncableFields();
$this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);
}
private function importOpportunityContacts(Opportunity $opportunity, array $associations): void
{
// Handle empty or missing contact associations
if (empty($associations)) {
// Remove all existing contact associations if none provided
$this->removeAllOpportunityContacts($opportunity);
return;
}
// Use differential sync approach for better performance and accuracy
$this->syncOpportunityContactsDifferential($opportunity, $associations);
}
/**
* Sync opportunity contacts using differential approach
* This compares current vs new associations and only makes necessary changes
*/
private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void
{
$currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);
$contactAssociationIds = array_keys($contactAssociations);
$contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);
$contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);
if (empty($contactsToAdd) && empty($contactsToRemove)) {
return;
}
$this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);
$this->removeContactAssociations($opportunity, $contactsToRemove);
$this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);
}
private function getCurrentContactCrmIds(Opportunity $opportunity): array
{
return $opportunity->contacts()
->pluck('contacts.crm_provider_id')
->toArray();
}
private function logContactAssociationChanges(
Opportunity $opportunity,
array $currentContactCrmIds,
array $contactAssociations,
array $contactsToAdd,
array $contactsToRemove
): void {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [
'opportunity_id' => $opportunity->getId(),
'current_contacts' => $currentContactCrmIds,
'new_contacts' => $contactAssociations,
'contacts_to_add' => $contactsToAdd,
'contacts_to_remove' => $contactsToRemove,
]);
}
private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void
{
if (empty($contactsToRemove)) {
return;
}
$contactsToDetach = $opportunity->contacts()
->whereIn('contacts.crm_provider_id', $contactsToRemove)
->pluck('contacts.id')
->toArray();
if (! empty($contactsToDetach)) {
$opportunity->contacts()->detach($contactsToDetach);
$this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_contact_crm_ids' => $contactsToRemove,
'removed_contact_count' => count($contactsToDetach),
]);
}
}
private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void
{
if (empty($contactsToAdd)) {
return;
}
$contactsAdded = [];
foreach ($contactsToAdd as $crmId) {
$id = $contactAssociations[$crmId];
if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {
$contactsAdded[] = $crmId;
}
}
$this->logAddedContacts($opportunity, $contactsAdded);
}
private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool
{
try {
$contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);
if (! $contact) {
return false;
}
return $this->performContactAttachment($opportunity, $contact, $crmId);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [
'opportunity_id' => $opportunity->getId(),
'contact_crm_id' => $crmId,
'error' => $e->getMessage(),
]);
return false;
}
}
private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool
{
try {
$opportunity->contacts()->attach($contact->getId(), [
'crm_provider_id' => $crmId,
]);
return true;
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [
'contact_id' => $contact->getId(),
'contact_crm_id' => $crmId,
'opportunity_id' => $opportunity->getId(),
]);
return false;
}
throw $e;
}
}
private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void
{
if (! empty($contactsAdded)) {
$this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [
'opportunity_id' => $opportunity->getId(),
'contacts_to_add_count' => count($contactsAdded),
'added_contact_crm_ids' => $contactsAdded,
'added_contacts_count' => count($contactsAdded),
]);
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<template>
<WelcomeLayout
title="Account disconnected"
textPosition="center"
:icon="faUnlink"
:class="$style.layout"
>
<div :class="$style.container" v-if="providersLoaded">
<p>
<strong>
It looks like your {{ localProvider.displayName }} account has become
disconnected
</strong>
</p>
<p :class="$style.small">Please re-connect to continue</p>
<p v-if="isInIframe">
We'll open the {{ localProvider.displayName }} authentication in a new
tab. Please return here and refresh the page once complete
</p>
<GoogleLikeButton
v-if="localProvider.viaIntegrationApp && crmTokenLoaded"
as="a"
:key="localProvider.name"
:brand-logo="localProvider.name"
:class="$style.connectButton"
@click="integrationAppOnClick"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
<GoogleLikeButton
v-if="!localProvider.viaIntegrationApp"
as="a"
:key="localProvider.name"
:href="`/auth/redirect/${localProvider.name}`"
:target="target"
:brand-logo="localProvider.name"
:class="$style.connectButton"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
</div>
<BuildInfo />
<KioskBanner />
</WelcomeLayout>
</template>
<script>
import window from "window";
import axios from "axios";
import { faUnlink } from "@fortawesome/pro-regular-svg-icons";
import isInIframe from "@/utils/isInIframe";
import BuildInfo from "@/components/layout/BuildInfo/BuildInfo.vue";
import KioskBanner from "@/components/shared/KioskBanner/KioskBanner.vue";
import WelcomeLayout from "@/components/layout/WelcomeLayout/WelcomeLayout.vue";
import GoogleLikeButton from "@/components/shared/Buttons/GoogleLikeButton.vue";
import { showSnackbarError, normalizeError } from "@/utils/index";
import { IntegrationAppClient } from "@integration-app/sdk";
export default {
name: "ConnectPage",
components: {
BuildInfo,
KioskBanner,
WelcomeLayout,
GoogleLikeButton,
},
data() {
return {
...window.connectData,
crmToken: null,
faUnlink,
isInIframe,
providers: [],
providersLoaded: false,
crmTokenLoaded: false,
};
},
computed: {
localProvider() {
return this.providers.find((e) => e.name === this.provider);
},
target() {
return this.isInIframe ? "_blank" : null;
},
},
created() {
this.getProviders();
},
mounted() {
this.showErrors();
},
watch: {
providersLoaded() {
if (this.providersLoaded) {
this.prepareIntegrationAppConnection();
}
},
},
methods: {
showErrors() {
if (!this.error) return;
showSnackbarError(this.error, undefined, undefined, false);
},
unwrapEntityResponse({ data }) {
return data.map(({ icon, name, displayName, viaIntegrationApp }) => {
return { icon, name, displayName, viaIntegrationApp };
});
},
async getProviders() {
try {
const response = await axios.get("/api/v1/connect-providers");
this.providers = this.unwrapEntityResponse(response);
this.providersLoaded = true;
} catch {
showSnackbarError(
"An error occurred, while loading form data (connect providers).",
);
}
},
async prepareIntegrationAppConnection() {
if (this.localProvider.viaIntegrationApp) {
try {
const response = await axios.get("/api/v1/integration-app-token");
this.crmToken = response.data.token;
this.crmTokenLoaded = true;
} catch (error) {
console.log(error);
showSnackbarError(
`An error occurred while preparing the page.
Try refreshing, if the error persists get in touch with the Jiminny team.`,
);
}
}
},
async integrationAppOnClick() {
const integrationApp = new IntegrationAppClient({
token: this.crmToken,
});
const connection = await integrationApp
.integration(this.localProvider.name)
.openNewConnection({
showPoweredBy: false,
allowMultipleConnections: false,
});
console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));
// [IntegrationApp] openNewConnection resolved: {
// "id":"69e0b41a67d0068c2ca0b48e",
// "name":"Zoho CRM",
// "userId":"1ece66c8-feb1-4df1-b321-21607daf4623",
// "tenantId":"69e0b3faef3e7b6248189289",
// "isTest":false,
// "connected":true,
// "state":"READY",
// "errors":[],
// "integrationId":"66fe6c913202f3a165e3c14d",
// "externalAppId":"6671653e7e2d642e4e41b0fa",
// "authOptionKey":"",
// "createdAt":"2026-04-16T10:04:10.420Z",
// "updatedAt":"2026-04-16T10:04:10.575Z",
// "retryAttempts":0,
// "isDeactivated":false
// }
if (connection && connection.disconnected !== true && connection.connected !== false) {
console.log('[IntegrationApp] connection condition matched');
try {
const saveRequest = await axios.post(
"/api/v1/integration-app-connect",
);
if (saveRequest.data && saveRequest.data.success === true) {
/** If all is good refresh the page here */
window.location = "/dashboard";
return;
}
throw new Error(saveRequest.data.message);
} catch (error) {
console.log(error);
showSnackbarError(normalizeError(error));
}
}
},
},
};
</script>
<style module lang="less" src="./connect.less"></style>
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.03046875,"top":0.017361112,"width":0.0453125,"height":0.022222223},"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"bounds":{"left":0.07578125,"top":0.017361112,"width":0.15898438,"height":0.022222223},"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.78515625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"bounds":{"left":0.803125,"top":0.017361112,"width":0.09765625,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9007813,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9140625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9273437,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96015626,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9734375,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9867188,"top":0.017361112,"width":0.013281226,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.12382813,"top":0.22083333,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.13867188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"bounds":{"left":0.1515625,"top":0.22013889,"width":0.0515625,"height":0.013888889},"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.21367188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.22539063,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.23554687,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.24570313,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2/4","depth":4,"bounds":{"left":0.26171875,"top":0.21944444,"width":0.030078124,"height":0.015277778},"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.29179686,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.30195314,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.31210938,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.32226562,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"bounds":{"left":0.38320312,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.049609374,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"33","depth":4,"bounds":{"left":0.3421875,"top":0.24583334,"width":0.012109375,"height":0.013194445},"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"bounds":{"left":0.35664064,"top":0.24583334,"width":0.009375,"height":0.013194445},"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.3683594,"top":0.24583334,"width":0.011328125,"height":0.013194445},"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.3816406,"top":0.24444444,"width":0.00859375,"height":0.015972223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.39023438,"top":0.24444444,"width":0.008203125,"height":0.015972223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\CollectionResponseAssociatedId;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\Account;\nuse Exception;\nuse Jiminny\\Component\\DealInsights\\Forecast\\Forecast;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Models\\Opportunity;\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Repositories\\Crm\\CrmEntityRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DealFieldsService;\nuse Jiminny\\Services\\Crm\\Hubspot\\OpportunitySyncStrategy\\HubspotSingleSyncStrategy;\nuse Jiminny\\Services\\Crm\\Hubspot\\WebhookSyncBatchProcessor;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Utils\\CurrencyFormatter;\n\n/**\n * Optimized sync methods for better performance\n * These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains\n */\ntrait OpportunitySyncTrait\n{\n private const int BATCH_SIZE = 100;\n private const int BATCH_PROCESS_SIZE = 800;\n\n protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n protected CrmEntityRepository $crmEntityRepository;\n protected DealFieldsService $dealFieldsService;\n\n private ?array $cachedClosedDealStages = null;\n private array $cachedBusinessProcesses = [];\n private array $cachedStages = [];\n\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n $parameters['config'] = $this->config;\n $syncCount = 0;\n $reportedTotal = 0;\n $lastSyncedId = [];\n\n try {\n foreach ($strategies as $strategyName => $syncStrategy) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .\n $strategyName\n );\n\n $total = 0;\n $lastId = null;\n $buffer = [];\n\n // HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies\n foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {\n $buffer[] = $hsOpportunity;\n\n // process every 800 rows (fits < 1 000 association limit)\n if (\\count($buffer) >= self::BATCH_PROCESS_SIZE) {\n $syncCount += $this->processOpportunityBatch($buffer);\n $buffer = [];\n }\n }\n\n // leftovers\n if ($buffer) {\n $syncCount += $this->processOpportunityBatch($buffer);\n }\n\n $reportedTotal += $total;\n $lastSyncedId = $lastId;\n }\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException | CrmException $e) {\n $this->handleSyncException($e, $parameters);\n }\n\n $this->logger->info(\n '[HubSpot] Synced opportunities',\n [\n 'team' => $this->team->getId(),\n 'sync_count' => $syncCount,\n 'total' => $reportedTotal,\n 'last_synced_id' => $lastSyncedId,\n ]\n );\n\n return $reportedTotal;\n }\n\n private function handleSyncException(\\Throwable $e, array $parameters): void\n {\n if (($parameters['since'] ?? null) instanceof Carbon) {\n $parameters['since'] = $parameters['since']->toDateTimeString();\n }\n $parameters['config'] = $this->config->getId();\n\n $this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [\n 'teamId' => $this->team->getUuid(),\n 'parameters' => $parameters,\n 'reason' => $e->getMessage(),\n ]);\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,\n );\n\n $parameters = [\n 'config' => $this->config,\n 'crm_id' => $crmId,\n ];\n\n try {\n if (! $strategy instanceof HubspotSingleSyncStrategy) {\n throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');\n }\n\n $hsOpportunity = $strategy->fetchOpportunity($parameters);\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->getUuid(),\n 'crmId' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);\n\n return $this->importOrUpdateOpportunity($hsOpportunity);\n }\n\n /**\n * Process webhook-collected opportunity batches.\n *\n * Drains Redis sets containing company CRM IDs collected from webhook events\n * and dispatches ImportOpportunityBatch jobs for batch processing.\n *\n * @return int Number of opportunity IDs dispatched to jobs\n */\n public function batchSyncOpportunities(): int\n {\n $configId = $this->team->getCrmConfiguration()->getId();\n\n return $this->batchProcessor->processBatchesForObjectType(\n WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,\n $configId\n );\n }\n\n /**\n * Import a batch of opportunities by their CRM IDs.\n * Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().\n *\n * @param array<string> $crmIds HubSpot deal CRM IDs\n *\n * @return array{success: array, failed_ids: array, errors?: array<string, string>}\n */\n public function importOpportunityBatchByIds(array $crmIds): array\n {\n $fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);\n\n $allDeals = [];\n foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {\n $deals = $this->client->getOpportunitiesByIds($chunk, $fields);\n foreach ($deals as $deal) {\n $allDeals[] = $deal;\n }\n }\n\n // IDs not returned by HubSpot are likely deleted or inaccessible deals.\n // These are not failures — retrying won't bring them back.\n $fetchedIds = array_map('strval', array_column($allDeals, 'id'));\n $notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));\n\n if (! empty($notFoundIds)) {\n $this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [\n 'teamId' => $this->team->getId(),\n 'notFoundCount' => \\count($notFoundIds),\n 'notFoundIds' => $notFoundIds,\n 'requestedCount' => \\count($crmIds),\n 'fetchedCount' => \\count($allDeals),\n ]);\n }\n\n if (empty($allDeals)) {\n return ['success' => [], 'failed_ids' => []];\n }\n\n return $this->importOpportunityBatch($allDeals);\n }\n\n private function getClosedDealStages(): array\n {\n if ($this->cachedClosedDealStages !== null) {\n return $this->cachedClosedDealStages;\n }\n\n $stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);\n $data = [\n 'lost' => [],\n 'won' => [],\n ];\n\n foreach ($stages as $stage) {\n if ($stage->probability == 0.00) {\n $data['lost'][] = $stage->crm_provider_id;\n }\n if ($stage->probability == 100.00) {\n $data['won'][] = $stage->crm_provider_id;\n }\n }\n\n $this->cachedClosedDealStages = $data;\n\n return $data;\n }\n\n /**\n * Import deals into the database with pre-fetched associations.\n *\n * API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT\n * caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()\n * where Laravel retries the whole job with backoff. After all retries exhausted,\n * failed() requeues all IDs to Redis.\n *\n * The per-deal loop catches exceptions individually. A deal can end up in three states:\n * - success: imported/updated successfully\n * - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)\n * These are permanent issues — retrying won't fix them.\n * - skipped (null): missing dependencies (no account, unknown pipeline/stage).\n * This is acceptable — the deal cannot be imported until those exist.\n */\n private function importOpportunityBatch(array $deals): array\n {\n $syncedOpportunities = [\n 'success' => [],\n 'failed_ids' => [],\n ];\n $dealIds = array_column($deals, 'id');\n\n // Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the\n // queue job retries the whole batch and eventually requeues all deal IDs back to Redis.\n try {\n $companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');\n $contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');\n\n $associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);\n\n $existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(\n $this->config,\n array_map('strval', $dealIds)\n );\n $existingCrmIdSet = array_flip($existingCrmIds);\n } catch (\\Throwable $e) {\n $this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [\n 'teamId' => $this->team->getId(),\n 'dealCount' => count($dealIds),\n 'error' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n foreach ($deals as $deal) {\n try {\n $deal['associations'] = $this->prepareAssociationsForOpportunity(\n $deal['id'],\n $companyAssociations,\n $contactAssociations,\n $associationsData\n );\n\n $syncedOpportunity = $this->importOrUpdateOpportunity(\n $deal,\n isset($existingCrmIdSet[(string) $deal['id']])\n );\n if ($syncedOpportunity) {\n $syncedOpportunities['success'][] = $syncedOpportunity;\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [\n 'teamId' => $this->team->getId(),\n 'crmId' => $deal['id'],\n 'error' => $e->getMessage(),\n ]);\n $syncedOpportunities['failed_ids'][] = $deal['id'];\n $syncedOpportunities['errors'][$deal['id']] = $e->getMessage();\n }\n }\n\n return $syncedOpportunities;\n }\n\n /**\n * Prepare associated entities for opportunities with optimized batch processing\n * Returns structured data with CRM ID to DB ID mappings for each opportunity\n */\n private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array\n {\n // Step 1: Collect all unique company and contact IDs from associations\n $allCompanyIds = $this->flattenAssociationIds($companyAssociations);\n $allContactIds = $this->flattenAssociationIds($contactAssociations);\n\n // Step 2: Batch sync missing entities and get CRM ID to DB ID mappings\n $companyIdMappings = [];\n $contactIdMappings = [];\n\n if (! empty($allCompanyIds)) {\n $companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);\n }\n\n if (! empty($allContactIds)) {\n $contactIdMappings = $this->prepareAssociatedContacts($allContactIds);\n }\n\n return [\n 'company_id_mappings' => $companyIdMappings,\n 'contact_id_mappings' => $contactIdMappings,\n ];\n }\n\n /**\n * Flatten association data to get unique IDs\n */\n private function flattenAssociationIds(array $associations): array\n {\n $ids = [];\n foreach ($associations as $dealAssociations) {\n if (is_array($dealAssociations)) {\n foreach ($dealAssociations as $id) {\n $ids[$id] = true;\n }\n }\n }\n\n return array_keys($ids);\n }\n\n /**\n * Batch sync missing accounts\n */\n private function prepareAssociatedAccounts(array $companyIds): array\n {\n // Find which accounts already exist\n $existingAccounts = $this->crmEntityRepository\n ->findAccountsByExternalIds($this->config, $companyIds);\n\n $existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();\n\n $existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {\n return [$account->getCrmProviderId() => $account->getId()];\n })->toArray();\n\n $missingCompanyIds = array_diff($companyIds, $existingCompanyIds);\n\n if (empty($missingCompanyIds)) {\n return $existingAccountsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [\n 'teamId' => $this->team->getUuid(),\n 'total_companies' => count($companyIds),\n 'existing_companies' => count($existingCompanyIds),\n 'missing_companies' => count($missingCompanyIds),\n ]);\n\n // we already have limit on opportunity ids count\n // Initialize variable before try block\n $syncedAccountsData = [];\n\n try {\n $syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [\n 'size' => count($missingCompanyIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedAccountsData = [];\n }\n\n return $existingAccountsData + $syncedAccountsData;\n }\n\n /**\n * Prepare associated contacts - find existing and sync missing ones\n * Returns mapping of CRM ID to DB ID\n */\n private function prepareAssociatedContacts(array $contactIds): array\n {\n // Find which contacts already exist\n $existingContacts = $this->crmEntityRepository\n ->findContactsByExternalIds($this->config, $contactIds);\n\n $existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();\n\n // Create mapping for existing contacts\n $existingContactsData = $existingContacts->mapWithKeys(function ($contact) {\n return [$contact->getCrmProviderId() => $contact->getId()];\n })->toArray();\n\n $missingContactIds = array_diff($contactIds, $existingContactIds);\n\n if (empty($missingContactIds)) {\n return $existingContactsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [\n 'teamId' => $this->team->getUuid(),\n 'total_contacts' => count($contactIds),\n 'existing_contacts' => count($existingContactIds),\n 'missing_contacts' => count($missingContactIds),\n ]);\n\n // Sync missing contacts using batch API\n try {\n $syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [\n 'size' => count($missingContactIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedContactsData = [];\n }\n\n return $existingContactsData + $syncedContactsData;\n }\n\n private function batchSyncCrmObjects(string $objectType, array $crmIds): array\n {\n $syncObjects = [];\n $crmObjectIds = array_values($crmIds);\n\n foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {\n try {\n $objects = $objectType === 'companies' ?\n $this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :\n $this->client->getContactsByIds($chunk, $this->getContactFields());\n\n foreach ($objects as $objectId => $objectData) {\n $this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [\n 'requested_count' => count($chunk),\n 'synced_count' => count($objects),\n ]);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [\n 'ids' => $chunk,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n return $syncObjects;\n }\n\n private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void\n {\n try {\n $object = $objectType === 'companies' ?\n $this->importAccount($objectData) :\n $this->importContact($objectData);\n\n if ($object) {\n $syncObjects[$object->getCrmProviderId()] = $object->getId();\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [\n 'id' => $objectId,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * Prepare associations for a single opportunity\n *\n * The return value is an array with the following structure:\n * [\n * 'companies' => [\n * $companyCrmId => $companyId,\n * ...\n * ],\n * 'contacts' => [\n * $contactCrmId => $contactId,\n * ...\n * ],\n * 'account_id' => $accountId,\n * ]\n */\n private function prepareAssociationsForOpportunity(\n string $oppCrmId,\n array $companyAssociations,\n array $contactAssociations,\n array $associationsData\n ): array {\n $associations = [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n\n $oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];\n foreach ($oppCompanyIds as $companyCrmId) {\n if (isset($associationsData['company_id_mappings'][$companyCrmId])) {\n $associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];\n\n // Set primary account (first company becomes primary account)\n if ($associations['account_id'] === null) {\n $associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];\n }\n }\n }\n\n $oppContactIds = $contactAssociations[$oppCrmId] ?? [];\n foreach ($oppContactIds as $contactCrmId) {\n if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {\n $associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];\n }\n }\n\n return $associations;\n }\n\n /**\n * Update only associations for an opportunity\n */\n private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void\n {\n // Update contact associations\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n // Update company (account) associations\n $this->updateOpportunityAccount($opportunity, $associations['account_id']);\n }\n\n /**\n * Remove all contact associations from an opportunity\n */\n private function removeAllOpportunityContacts(Opportunity $opportunity): void\n {\n $currentCount = (int) $opportunity->contacts()->count();\n\n if ($currentCount > 0) {\n $opportunity->contacts()->detach();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_count' => $currentCount,\n ]);\n }\n }\n\n private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void\n {\n if ($accountId === null) {\n // No account ID provided - keep current account\n return;\n }\n\n $currentAccountId = $opportunity->getAccountId();\n\n // Only update if account has changed\n if ($currentAccountId !== $accountId) {\n $opportunity->account_id = $accountId;\n $opportunity->save();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [\n 'opportunity_id' => $opportunity->getId(),\n 'old_account_id' => $currentAccountId,\n 'new_account_id' => $accountId,\n ]);\n }\n }\n\n /**\n * Find existing opportunities by external IDs (OPTIMIZED VERSION)\n * Uses batch query for better performance\n */\n private function findExistingOpportunities(array $crmIds): Collection\n {\n return $this->crmEntityRepository\n ->findOpportunitiesByExternalIds($this->config, $crmIds);\n }\n\n private function processOpportunityBatch(array $opportunities): int\n {\n $syncedOpportunities = $this->importOpportunityBatch($opportunities);\n\n return count($syncedOpportunities['success'] ?? []);\n }\n\n /**\n * Convert single deal associations from HubSpot format to internal format\n * Handles both HubSpot SDK objects and array formats\n *\n * @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed\n *\n * @return array Processed associations with DB IDs\n */\n private function convertDealAssociations(array $opportunityAssociations): array\n {\n $associations = $this->initializeAssociationsStructure();\n\n if (empty($opportunityAssociations)) {\n return $associations;\n }\n\n $associationIds = $this->extractAssociationIds($opportunityAssociations);\n\n $this->processCompanyAssociations($associationIds, $associations);\n $this->processContactAssociations($associationIds, $associations);\n\n return $associations;\n }\n\n private function initializeAssociationsStructure(): array\n {\n return [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n }\n\n private function extractAssociationIds(array $opportunityAssociations): array\n {\n $associationIds = [];\n\n foreach ($opportunityAssociations as $type => $associationData) {\n if (! empty($associationData)) {\n $associationIds[$type] = $this->convertSingleDealAssociations($associationData);\n }\n }\n\n return $associationIds;\n }\n\n private function processCompanyAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['companies'])) {\n return;\n }\n\n $companyId = $associationIds['companies'][0];\n $account = $this->findOrSyncAccount($companyId);\n\n if ($account instanceof Account) {\n $associations['companies'][$companyId] = $account->getId();\n $associations['account_id'] = $account->getId();\n }\n }\n\n private function processContactAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['contacts'])) {\n return;\n }\n\n foreach ($associationIds['contacts'] as $contactId) {\n $contact = $this->findOrSyncContact($contactId);\n\n if ($contact instanceof Contact) {\n $associations['contacts'][$contactId] = $contact->getId();\n }\n }\n }\n\n private function findOrSyncAccount(string $companyId): ?Account\n {\n $account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);\n\n if (! $account instanceof Account) {\n $account = $this->syncAccount($companyId);\n }\n\n return $account;\n }\n\n private function findOrSyncContact(string $contactId): ?Contact\n {\n $contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);\n\n if (! $contact instanceof Contact) {\n $contact = $this->syncContact($contactId);\n }\n\n return $contact;\n }\n\n private function convertSingleDealAssociations($opportunityAssociations = null): array\n {\n $associationData = [];\n\n if ($opportunityAssociations === null) {\n return $associationData;\n }\n\n // Handle array input (from extractAssociationIds)\n if (is_array($opportunityAssociations)) {\n return $opportunityAssociations;\n }\n\n // Handle CollectionResponseAssociatedId object\n if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {\n foreach ($opportunityAssociations->getResults() as $association) {\n $associationData[] = $association->getId();\n }\n }\n\n return $associationData;\n }\n\n private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity\n {\n if (empty($crmData['properties'])) {\n return null;\n }\n\n $crmId = (string) $crmData['id'];\n $properties = $crmData['properties'];\n $associations = $crmData['associations'] ?? [];\n\n $opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(\n $this->config,\n $crmId\n );\n\n if ($opportunityExists) {\n return $this->updateOpportunity($crmId, $properties, $associations);\n } else {\n return $this->createOpportunity($crmId, $properties, $associations);\n }\n }\n\n /**\n * Create new opportunity\n */\n private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n if (! $accountId) {\n return null;\n }\n\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n if (! $businessProcess) {\n return null;\n }\n\n $stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);\n if (! $stage) {\n return null;\n }\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n }\n\n /**\n * Update existing opportunity\n */\n private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n $stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->updateOpportunityAssociations($opportunity, $associations);\n\n return $opportunity;\n }\n\n private function resolveAccountId(array $associations): ?int\n {\n if (! empty($associations['accountId'])) {\n return $associations['accountId'];\n }\n\n if (empty($associations)) {\n return null;\n }\n\n // we can't resolve multiple account ids (currently SDK returns one company)\n foreach ($associations['companies'] as $accountId) {\n return $accountId;\n }\n\n return null;\n }\n\n private function buildOpportunityData(\n array $properties,\n ?int $accountId,\n ?BusinessProcess $businessProcess,\n ?Stage $stage\n ): array {\n $ownerId = null;\n $profile = null;\n if (! empty($properties['hubspot_owner_id'])) {\n $ownerId = $properties['hubspot_owner_id'];\n $profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);\n }\n\n $name = 'Unknown';\n if (isset($properties['dealname'])) {\n $name = mb_strimwidth($properties['dealname'], 0, 128);\n }\n\n $amount = $this->resolveAmount($properties);\n $currency = $properties['deal_currency_code'] ?? null;\n\n $closeDate = null;\n if (! empty($properties['closedate'])) {\n $closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');\n }\n\n $remotelyCreatedAt = null;\n if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {\n $date = $this->parseCleanDatetime($properties['createdate']);\n $remotelyCreatedAt = $date?->format('Y-m-d H:i:s');\n }\n\n $closedStages = $this->getClosedDealStages();\n $isWon = in_array($properties['dealstage'], $closedStages['won']);\n $isLost = in_array($properties['dealstage'], $closedStages['lost']);\n\n $data = [\n 'team_id' => $this->team->getId(),\n 'user_id' => $profile ? $profile->user_id : null,\n 'owner_id' => $ownerId,\n 'name' => $name,\n 'value' => ! empty($amount) ? $amount : null,\n 'currency_code' => CurrencyFormatter::formatCode($currency),\n 'close_date' => $closeDate,\n 'is_closed' => $isWon || $isLost,\n 'is_won' => $isWon,\n 'remotely_created_at' => $remotelyCreatedAt,\n 'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),\n 'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),\n ];\n\n if ($accountId) {\n $data['account_id'] = $accountId;\n }\n\n if ($stage) {\n $data['stage_id'] = $stage->id;\n }\n\n if ($businessProcess) {\n $recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);\n if ($recordType) {\n $data['record_type_id'] = $recordType->id;\n }\n }\n\n return $data;\n }\n\n private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess\n {\n if ($pipelineId === null) {\n return null;\n }\n\n if (isset($this->cachedBusinessProcesses[$pipelineId])) {\n return $this->cachedBusinessProcesses[$pipelineId];\n }\n\n $businessProcess = $this->getBusinessProcess($pipelineId);\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->importStages();\n $businessProcess = $this->getBusinessProcess($pipelineId);\n }\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->logger->info(\n '[HubSpot] Deal is not attached to a pipeline',\n [\n 'pipeline' => $pipelineId]\n );\n }\n\n $this->cachedBusinessProcesses[$pipelineId] = $businessProcess;\n\n return $businessProcess;\n }\n\n private function getBusinessProcess(string $pipelineId): ?BusinessProcess\n {\n return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);\n }\n\n private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage\n {\n if (empty($stageId)) {\n return null;\n }\n\n $cacheKey = $businessProcess->getId() . ':' . $stageId;\n if (isset($this->cachedStages[$cacheKey])) {\n return $this->cachedStages[$cacheKey];\n }\n\n $stage = $this->crmEntityRepository->getPipelineStageByConditions(\n $businessProcess,\n [\n 'crm_provider_id' => $stageId,\n 'type' => Stage::TYPE_OPPORTUNITY,\n ]\n );\n\n if ($stage === null) {\n $this->importStages(null, $stageId);\n }\n\n if ($stage === null) {\n $this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);\n }\n\n $this->cachedStages[$cacheKey] = $stage;\n\n return $stage;\n }\n\n private function resolveAmount(array $properties): ?string\n {\n $amount = null;\n if (! empty($properties['amount'])) {\n $amount = str_replace(',', '', $properties['amount']);\n }\n\n if ($this->config->hasDefaultCurrencyFieldSet()) {\n $valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();\n $amount = $properties[$valueFieldName] ?? $amount;\n }\n\n return $amount;\n }\n\n private function parseCleanDatetime(string $datetime): ?Carbon\n {\n // Treat pre-1980 values as invalid\n $minValidDate = Carbon::parse('1980-01-01 00:00:00');\n\n try {\n $date = Carbon::parse($datetime);\n\n if ($minValidDate->gt($date)) {\n return null;\n }\n\n return $date;\n } catch (Exception) {\n return null; // On parse error, treat as null\n }\n }\n\n private function resolveDealProbability(?string $stageProbability): int\n {\n if ($stageProbability === null) {\n return 0;\n }\n\n $probability = (float) $stageProbability;\n\n return $probability > 1 ? 0 : (int) ($probability * 100);\n }\n\n private function resolveForecastCategory(?string $forecastCategory): string\n {\n if (! $forecastCategory) {\n return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;\n }\n\n $forecastCategory = str_replace('_', ' ', $forecastCategory);\n\n return ucwords(strtolower($forecastCategory));\n }\n\n private function importExternalFieldData(array $properties, int $opportunityId): void\n {\n $crmFields = $this->getOpportunitySyncableFields();\n $this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);\n }\n\n private function importOpportunityContacts(Opportunity $opportunity, array $associations): void\n {\n // Handle empty or missing contact associations\n if (empty($associations)) {\n // Remove all existing contact associations if none provided\n $this->removeAllOpportunityContacts($opportunity);\n\n return;\n }\n\n // Use differential sync approach for better performance and accuracy\n $this->syncOpportunityContactsDifferential($opportunity, $associations);\n }\n\n /**\n * Sync opportunity contacts using differential approach\n * This compares current vs new associations and only makes necessary changes\n */\n private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void\n {\n $currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);\n $contactAssociationIds = array_keys($contactAssociations);\n\n $contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);\n $contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);\n\n if (empty($contactsToAdd) && empty($contactsToRemove)) {\n return;\n }\n\n $this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);\n\n $this->removeContactAssociations($opportunity, $contactsToRemove);\n $this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);\n }\n\n private function getCurrentContactCrmIds(Opportunity $opportunity): array\n {\n return $opportunity->contacts()\n ->pluck('contacts.crm_provider_id')\n ->toArray();\n }\n\n private function logContactAssociationChanges(\n Opportunity $opportunity,\n array $currentContactCrmIds,\n array $contactAssociations,\n array $contactsToAdd,\n array $contactsToRemove\n ): void {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [\n 'opportunity_id' => $opportunity->getId(),\n 'current_contacts' => $currentContactCrmIds,\n 'new_contacts' => $contactAssociations,\n 'contacts_to_add' => $contactsToAdd,\n 'contacts_to_remove' => $contactsToRemove,\n ]);\n }\n\n private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void\n {\n if (empty($contactsToRemove)) {\n return;\n }\n\n $contactsToDetach = $opportunity->contacts()\n ->whereIn('contacts.crm_provider_id', $contactsToRemove)\n ->pluck('contacts.id')\n ->toArray();\n\n if (! empty($contactsToDetach)) {\n $opportunity->contacts()->detach($contactsToDetach);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_contact_crm_ids' => $contactsToRemove,\n 'removed_contact_count' => count($contactsToDetach),\n ]);\n }\n }\n\n private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void\n {\n if (empty($contactsToAdd)) {\n return;\n }\n\n $contactsAdded = [];\n foreach ($contactsToAdd as $crmId) {\n $id = $contactAssociations[$crmId];\n\n if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {\n $contactsAdded[] = $crmId;\n }\n }\n\n $this->logAddedContacts($opportunity, $contactsAdded);\n }\n\n private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool\n {\n try {\n $contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);\n\n if (! $contact) {\n return false;\n }\n\n return $this->performContactAttachment($opportunity, $contact, $crmId);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [\n 'opportunity_id' => $opportunity->getId(),\n 'contact_crm_id' => $crmId,\n 'error' => $e->getMessage(),\n ]);\n\n return false;\n }\n }\n\n private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool\n {\n try {\n $opportunity->contacts()->attach($contact->getId(), [\n 'crm_provider_id' => $crmId,\n ]);\n\n return true;\n } catch (\\Illuminate\\Database\\QueryException $e) {\n if (str_contains($e->getMessage(), 'Duplicate entry')) {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [\n 'contact_id' => $contact->getId(),\n 'contact_crm_id' => $crmId,\n 'opportunity_id' => $opportunity->getId(),\n ]);\n\n return false;\n }\n\n throw $e;\n }\n }\n\n private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void\n {\n if (! empty($contactsAdded)) {\n $this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'contacts_to_add_count' => count($contactsAdded),\n 'added_contact_crm_ids' => $contactsAdded,\n 'added_contacts_count' => count($contactsAdded),\n ]);\n }\n }\n}","depth":4,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\CollectionResponseAssociatedId;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\Account;\nuse Exception;\nuse Jiminny\\Component\\DealInsights\\Forecast\\Forecast;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Models\\Opportunity;\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Repositories\\Crm\\CrmEntityRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DealFieldsService;\nuse Jiminny\\Services\\Crm\\Hubspot\\OpportunitySyncStrategy\\HubspotSingleSyncStrategy;\nuse Jiminny\\Services\\Crm\\Hubspot\\WebhookSyncBatchProcessor;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Utils\\CurrencyFormatter;\n\n/**\n * Optimized sync methods for better performance\n * These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains\n */\ntrait OpportunitySyncTrait\n{\n private const int BATCH_SIZE = 100;\n private const int BATCH_PROCESS_SIZE = 800;\n\n protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n protected CrmEntityRepository $crmEntityRepository;\n protected DealFieldsService $dealFieldsService;\n\n private ?array $cachedClosedDealStages = null;\n private array $cachedBusinessProcesses = [];\n private array $cachedStages = [];\n\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n $parameters['config'] = $this->config;\n $syncCount = 0;\n $reportedTotal = 0;\n $lastSyncedId = [];\n\n try {\n foreach ($strategies as $strategyName => $syncStrategy) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .\n $strategyName\n );\n\n $total = 0;\n $lastId = null;\n $buffer = [];\n\n // HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies\n foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {\n $buffer[] = $hsOpportunity;\n\n // process every 800 rows (fits < 1 000 association limit)\n if (\\count($buffer) >= self::BATCH_PROCESS_SIZE) {\n $syncCount += $this->processOpportunityBatch($buffer);\n $buffer = [];\n }\n }\n\n // leftovers\n if ($buffer) {\n $syncCount += $this->processOpportunityBatch($buffer);\n }\n\n $reportedTotal += $total;\n $lastSyncedId = $lastId;\n }\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException | CrmException $e) {\n $this->handleSyncException($e, $parameters);\n }\n\n $this->logger->info(\n '[HubSpot] Synced opportunities',\n [\n 'team' => $this->team->getId(),\n 'sync_count' => $syncCount,\n 'total' => $reportedTotal,\n 'last_synced_id' => $lastSyncedId,\n ]\n );\n\n return $reportedTotal;\n }\n\n private function handleSyncException(\\Throwable $e, array $parameters): void\n {\n if (($parameters['since'] ?? null) instanceof Carbon) {\n $parameters['since'] = $parameters['since']->toDateTimeString();\n }\n $parameters['config'] = $this->config->getId();\n\n $this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [\n 'teamId' => $this->team->getUuid(),\n 'parameters' => $parameters,\n 'reason' => $e->getMessage(),\n ]);\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,\n );\n\n $parameters = [\n 'config' => $this->config,\n 'crm_id' => $crmId,\n ];\n\n try {\n if (! $strategy instanceof HubspotSingleSyncStrategy) {\n throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');\n }\n\n $hsOpportunity = $strategy->fetchOpportunity($parameters);\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->getUuid(),\n 'crmId' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);\n\n return $this->importOrUpdateOpportunity($hsOpportunity);\n }\n\n /**\n * Process webhook-collected opportunity batches.\n *\n * Drains Redis sets containing company CRM IDs collected from webhook events\n * and dispatches ImportOpportunityBatch jobs for batch processing.\n *\n * @return int Number of opportunity IDs dispatched to jobs\n */\n public function batchSyncOpportunities(): int\n {\n $configId = $this->team->getCrmConfiguration()->getId();\n\n return $this->batchProcessor->processBatchesForObjectType(\n WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,\n $configId\n );\n }\n\n /**\n * Import a batch of opportunities by their CRM IDs.\n * Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().\n *\n * @param array<string> $crmIds HubSpot deal CRM IDs\n *\n * @return array{success: array, failed_ids: array, errors?: array<string, string>}\n */\n public function importOpportunityBatchByIds(array $crmIds): array\n {\n $fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);\n\n $allDeals = [];\n foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {\n $deals = $this->client->getOpportunitiesByIds($chunk, $fields);\n foreach ($deals as $deal) {\n $allDeals[] = $deal;\n }\n }\n\n // IDs not returned by HubSpot are likely deleted or inaccessible deals.\n // These are not failures — retrying won't bring them back.\n $fetchedIds = array_map('strval', array_column($allDeals, 'id'));\n $notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));\n\n if (! empty($notFoundIds)) {\n $this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [\n 'teamId' => $this->team->getId(),\n 'notFoundCount' => \\count($notFoundIds),\n 'notFoundIds' => $notFoundIds,\n 'requestedCount' => \\count($crmIds),\n 'fetchedCount' => \\count($allDeals),\n ]);\n }\n\n if (empty($allDeals)) {\n return ['success' => [], 'failed_ids' => []];\n }\n\n return $this->importOpportunityBatch($allDeals);\n }\n\n private function getClosedDealStages(): array\n {\n if ($this->cachedClosedDealStages !== null) {\n return $this->cachedClosedDealStages;\n }\n\n $stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);\n $data = [\n 'lost' => [],\n 'won' => [],\n ];\n\n foreach ($stages as $stage) {\n if ($stage->probability == 0.00) {\n $data['lost'][] = $stage->crm_provider_id;\n }\n if ($stage->probability == 100.00) {\n $data['won'][] = $stage->crm_provider_id;\n }\n }\n\n $this->cachedClosedDealStages = $data;\n\n return $data;\n }\n\n /**\n * Import deals into the database with pre-fetched associations.\n *\n * API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT\n * caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()\n * where Laravel retries the whole job with backoff. After all retries exhausted,\n * failed() requeues all IDs to Redis.\n *\n * The per-deal loop catches exceptions individually. A deal can end up in three states:\n * - success: imported/updated successfully\n * - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)\n * These are permanent issues — retrying won't fix them.\n * - skipped (null): missing dependencies (no account, unknown pipeline/stage).\n * This is acceptable — the deal cannot be imported until those exist.\n */\n private function importOpportunityBatch(array $deals): array\n {\n $syncedOpportunities = [\n 'success' => [],\n 'failed_ids' => [],\n ];\n $dealIds = array_column($deals, 'id');\n\n // Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the\n // queue job retries the whole batch and eventually requeues all deal IDs back to Redis.\n try {\n $companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');\n $contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');\n\n $associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);\n\n $existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(\n $this->config,\n array_map('strval', $dealIds)\n );\n $existingCrmIdSet = array_flip($existingCrmIds);\n } catch (\\Throwable $e) {\n $this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [\n 'teamId' => $this->team->getId(),\n 'dealCount' => count($dealIds),\n 'error' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n foreach ($deals as $deal) {\n try {\n $deal['associations'] = $this->prepareAssociationsForOpportunity(\n $deal['id'],\n $companyAssociations,\n $contactAssociations,\n $associationsData\n );\n\n $syncedOpportunity = $this->importOrUpdateOpportunity(\n $deal,\n isset($existingCrmIdSet[(string) $deal['id']])\n );\n if ($syncedOpportunity) {\n $syncedOpportunities['success'][] = $syncedOpportunity;\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [\n 'teamId' => $this->team->getId(),\n 'crmId' => $deal['id'],\n 'error' => $e->getMessage(),\n ]);\n $syncedOpportunities['failed_ids'][] = $deal['id'];\n $syncedOpportunities['errors'][$deal['id']] = $e->getMessage();\n }\n }\n\n return $syncedOpportunities;\n }\n\n /**\n * Prepare associated entities for opportunities with optimized batch processing\n * Returns structured data with CRM ID to DB ID mappings for each opportunity\n */\n private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array\n {\n // Step 1: Collect all unique company and contact IDs from associations\n $allCompanyIds = $this->flattenAssociationIds($companyAssociations);\n $allContactIds = $this->flattenAssociationIds($contactAssociations);\n\n // Step 2: Batch sync missing entities and get CRM ID to DB ID mappings\n $companyIdMappings = [];\n $contactIdMappings = [];\n\n if (! empty($allCompanyIds)) {\n $companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);\n }\n\n if (! empty($allContactIds)) {\n $contactIdMappings = $this->prepareAssociatedContacts($allContactIds);\n }\n\n return [\n 'company_id_mappings' => $companyIdMappings,\n 'contact_id_mappings' => $contactIdMappings,\n ];\n }\n\n /**\n * Flatten association data to get unique IDs\n */\n private function flattenAssociationIds(array $associations): array\n {\n $ids = [];\n foreach ($associations as $dealAssociations) {\n if (is_array($dealAssociations)) {\n foreach ($dealAssociations as $id) {\n $ids[$id] = true;\n }\n }\n }\n\n return array_keys($ids);\n }\n\n /**\n * Batch sync missing accounts\n */\n private function prepareAssociatedAccounts(array $companyIds): array\n {\n // Find which accounts already exist\n $existingAccounts = $this->crmEntityRepository\n ->findAccountsByExternalIds($this->config, $companyIds);\n\n $existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();\n\n $existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {\n return [$account->getCrmProviderId() => $account->getId()];\n })->toArray();\n\n $missingCompanyIds = array_diff($companyIds, $existingCompanyIds);\n\n if (empty($missingCompanyIds)) {\n return $existingAccountsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [\n 'teamId' => $this->team->getUuid(),\n 'total_companies' => count($companyIds),\n 'existing_companies' => count($existingCompanyIds),\n 'missing_companies' => count($missingCompanyIds),\n ]);\n\n // we already have limit on opportunity ids count\n // Initialize variable before try block\n $syncedAccountsData = [];\n\n try {\n $syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [\n 'size' => count($missingCompanyIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedAccountsData = [];\n }\n\n return $existingAccountsData + $syncedAccountsData;\n }\n\n /**\n * Prepare associated contacts - find existing and sync missing ones\n * Returns mapping of CRM ID to DB ID\n */\n private function prepareAssociatedContacts(array $contactIds): array\n {\n // Find which contacts already exist\n $existingContacts = $this->crmEntityRepository\n ->findContactsByExternalIds($this->config, $contactIds);\n\n $existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();\n\n // Create mapping for existing contacts\n $existingContactsData = $existingContacts->mapWithKeys(function ($contact) {\n return [$contact->getCrmProviderId() => $contact->getId()];\n })->toArray();\n\n $missingContactIds = array_diff($contactIds, $existingContactIds);\n\n if (empty($missingContactIds)) {\n return $existingContactsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [\n 'teamId' => $this->team->getUuid(),\n 'total_contacts' => count($contactIds),\n 'existing_contacts' => count($existingContactIds),\n 'missing_contacts' => count($missingContactIds),\n ]);\n\n // Sync missing contacts using batch API\n try {\n $syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [\n 'size' => count($missingContactIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedContactsData = [];\n }\n\n return $existingContactsData + $syncedContactsData;\n }\n\n private function batchSyncCrmObjects(string $objectType, array $crmIds): array\n {\n $syncObjects = [];\n $crmObjectIds = array_values($crmIds);\n\n foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {\n try {\n $objects = $objectType === 'companies' ?\n $this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :\n $this->client->getContactsByIds($chunk, $this->getContactFields());\n\n foreach ($objects as $objectId => $objectData) {\n $this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [\n 'requested_count' => count($chunk),\n 'synced_count' => count($objects),\n ]);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [\n 'ids' => $chunk,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n return $syncObjects;\n }\n\n private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void\n {\n try {\n $object = $objectType === 'companies' ?\n $this->importAccount($objectData) :\n $this->importContact($objectData);\n\n if ($object) {\n $syncObjects[$object->getCrmProviderId()] = $object->getId();\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [\n 'id' => $objectId,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * Prepare associations for a single opportunity\n *\n * The return value is an array with the following structure:\n * [\n * 'companies' => [\n * $companyCrmId => $companyId,\n * ...\n * ],\n * 'contacts' => [\n * $contactCrmId => $contactId,\n * ...\n * ],\n * 'account_id' => $accountId,\n * ]\n */\n private function prepareAssociationsForOpportunity(\n string $oppCrmId,\n array $companyAssociations,\n array $contactAssociations,\n array $associationsData\n ): array {\n $associations = [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n\n $oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];\n foreach ($oppCompanyIds as $companyCrmId) {\n if (isset($associationsData['company_id_mappings'][$companyCrmId])) {\n $associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];\n\n // Set primary account (first company becomes primary account)\n if ($associations['account_id'] === null) {\n $associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];\n }\n }\n }\n\n $oppContactIds = $contactAssociations[$oppCrmId] ?? [];\n foreach ($oppContactIds as $contactCrmId) {\n if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {\n $associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];\n }\n }\n\n return $associations;\n }\n\n /**\n * Update only associations for an opportunity\n */\n private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void\n {\n // Update contact associations\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n // Update company (account) associations\n $this->updateOpportunityAccount($opportunity, $associations['account_id']);\n }\n\n /**\n * Remove all contact associations from an opportunity\n */\n private function removeAllOpportunityContacts(Opportunity $opportunity): void\n {\n $currentCount = (int) $opportunity->contacts()->count();\n\n if ($currentCount > 0) {\n $opportunity->contacts()->detach();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_count' => $currentCount,\n ]);\n }\n }\n\n private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void\n {\n if ($accountId === null) {\n // No account ID provided - keep current account\n return;\n }\n\n $currentAccountId = $opportunity->getAccountId();\n\n // Only update if account has changed\n if ($currentAccountId !== $accountId) {\n $opportunity->account_id = $accountId;\n $opportunity->save();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [\n 'opportunity_id' => $opportunity->getId(),\n 'old_account_id' => $currentAccountId,\n 'new_account_id' => $accountId,\n ]);\n }\n }\n\n /**\n * Find existing opportunities by external IDs (OPTIMIZED VERSION)\n * Uses batch query for better performance\n */\n private function findExistingOpportunities(array $crmIds): Collection\n {\n return $this->crmEntityRepository\n ->findOpportunitiesByExternalIds($this->config, $crmIds);\n }\n\n private function processOpportunityBatch(array $opportunities): int\n {\n $syncedOpportunities = $this->importOpportunityBatch($opportunities);\n\n return count($syncedOpportunities['success'] ?? []);\n }\n\n /**\n * Convert single deal associations from HubSpot format to internal format\n * Handles both HubSpot SDK objects and array formats\n *\n * @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed\n *\n * @return array Processed associations with DB IDs\n */\n private function convertDealAssociations(array $opportunityAssociations): array\n {\n $associations = $this->initializeAssociationsStructure();\n\n if (empty($opportunityAssociations)) {\n return $associations;\n }\n\n $associationIds = $this->extractAssociationIds($opportunityAssociations);\n\n $this->processCompanyAssociations($associationIds, $associations);\n $this->processContactAssociations($associationIds, $associations);\n\n return $associations;\n }\n\n private function initializeAssociationsStructure(): array\n {\n return [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n }\n\n private function extractAssociationIds(array $opportunityAssociations): array\n {\n $associationIds = [];\n\n foreach ($opportunityAssociations as $type => $associationData) {\n if (! empty($associationData)) {\n $associationIds[$type] = $this->convertSingleDealAssociations($associationData);\n }\n }\n\n return $associationIds;\n }\n\n private function processCompanyAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['companies'])) {\n return;\n }\n\n $companyId = $associationIds['companies'][0];\n $account = $this->findOrSyncAccount($companyId);\n\n if ($account instanceof Account) {\n $associations['companies'][$companyId] = $account->getId();\n $associations['account_id'] = $account->getId();\n }\n }\n\n private function processContactAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['contacts'])) {\n return;\n }\n\n foreach ($associationIds['contacts'] as $contactId) {\n $contact = $this->findOrSyncContact($contactId);\n\n if ($contact instanceof Contact) {\n $associations['contacts'][$contactId] = $contact->getId();\n }\n }\n }\n\n private function findOrSyncAccount(string $companyId): ?Account\n {\n $account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);\n\n if (! $account instanceof Account) {\n $account = $this->syncAccount($companyId);\n }\n\n return $account;\n }\n\n private function findOrSyncContact(string $contactId): ?Contact\n {\n $contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);\n\n if (! $contact instanceof Contact) {\n $contact = $this->syncContact($contactId);\n }\n\n return $contact;\n }\n\n private function convertSingleDealAssociations($opportunityAssociations = null): array\n {\n $associationData = [];\n\n if ($opportunityAssociations === null) {\n return $associationData;\n }\n\n // Handle array input (from extractAssociationIds)\n if (is_array($opportunityAssociations)) {\n return $opportunityAssociations;\n }\n\n // Handle CollectionResponseAssociatedId object\n if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {\n foreach ($opportunityAssociations->getResults() as $association) {\n $associationData[] = $association->getId();\n }\n }\n\n return $associationData;\n }\n\n private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity\n {\n if (empty($crmData['properties'])) {\n return null;\n }\n\n $crmId = (string) $crmData['id'];\n $properties = $crmData['properties'];\n $associations = $crmData['associations'] ?? [];\n\n $opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(\n $this->config,\n $crmId\n );\n\n if ($opportunityExists) {\n return $this->updateOpportunity($crmId, $properties, $associations);\n } else {\n return $this->createOpportunity($crmId, $properties, $associations);\n }\n }\n\n /**\n * Create new opportunity\n */\n private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n if (! $accountId) {\n return null;\n }\n\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n if (! $businessProcess) {\n return null;\n }\n\n $stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);\n if (! $stage) {\n return null;\n }\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n }\n\n /**\n * Update existing opportunity\n */\n private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n $stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->updateOpportunityAssociations($opportunity, $associations);\n\n return $opportunity;\n }\n\n private function resolveAccountId(array $associations): ?int\n {\n if (! empty($associations['accountId'])) {\n return $associations['accountId'];\n }\n\n if (empty($associations)) {\n return null;\n }\n\n // we can't resolve multiple account ids (currently SDK returns one company)\n foreach ($associations['companies'] as $accountId) {\n return $accountId;\n }\n\n return null;\n }\n\n private function buildOpportunityData(\n array $properties,\n ?int $accountId,\n ?BusinessProcess $businessProcess,\n ?Stage $stage\n ): array {\n $ownerId = null;\n $profile = null;\n if (! empty($properties['hubspot_owner_id'])) {\n $ownerId = $properties['hubspot_owner_id'];\n $profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);\n }\n\n $name = 'Unknown';\n if (isset($properties['dealname'])) {\n $name = mb_strimwidth($properties['dealname'], 0, 128);\n }\n\n $amount = $this->resolveAmount($properties);\n $currency = $properties['deal_currency_code'] ?? null;\n\n $closeDate = null;\n if (! empty($properties['closedate'])) {\n $closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');\n }\n\n $remotelyCreatedAt = null;\n if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {\n $date = $this->parseCleanDatetime($properties['createdate']);\n $remotelyCreatedAt = $date?->format('Y-m-d H:i:s');\n }\n\n $closedStages = $this->getClosedDealStages();\n $isWon = in_array($properties['dealstage'], $closedStages['won']);\n $isLost = in_array($properties['dealstage'], $closedStages['lost']);\n\n $data = [\n 'team_id' => $this->team->getId(),\n 'user_id' => $profile ? $profile->user_id : null,\n 'owner_id' => $ownerId,\n 'name' => $name,\n 'value' => ! empty($amount) ? $amount : null,\n 'currency_code' => CurrencyFormatter::formatCode($currency),\n 'close_date' => $closeDate,\n 'is_closed' => $isWon || $isLost,\n 'is_won' => $isWon,\n 'remotely_created_at' => $remotelyCreatedAt,\n 'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),\n 'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),\n ];\n\n if ($accountId) {\n $data['account_id'] = $accountId;\n }\n\n if ($stage) {\n $data['stage_id'] = $stage->id;\n }\n\n if ($businessProcess) {\n $recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);\n if ($recordType) {\n $data['record_type_id'] = $recordType->id;\n }\n }\n\n return $data;\n }\n\n private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess\n {\n if ($pipelineId === null) {\n return null;\n }\n\n if (isset($this->cachedBusinessProcesses[$pipelineId])) {\n return $this->cachedBusinessProcesses[$pipelineId];\n }\n\n $businessProcess = $this->getBusinessProcess($pipelineId);\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->importStages();\n $businessProcess = $this->getBusinessProcess($pipelineId);\n }\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->logger->info(\n '[HubSpot] Deal is not attached to a pipeline',\n [\n 'pipeline' => $pipelineId]\n );\n }\n\n $this->cachedBusinessProcesses[$pipelineId] = $businessProcess;\n\n return $businessProcess;\n }\n\n private function getBusinessProcess(string $pipelineId): ?BusinessProcess\n {\n return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);\n }\n\n private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage\n {\n if (empty($stageId)) {\n return null;\n }\n\n $cacheKey = $businessProcess->getId() . ':' . $stageId;\n if (isset($this->cachedStages[$cacheKey])) {\n return $this->cachedStages[$cacheKey];\n }\n\n $stage = $this->crmEntityRepository->getPipelineStageByConditions(\n $businessProcess,\n [\n 'crm_provider_id' => $stageId,\n 'type' => Stage::TYPE_OPPORTUNITY,\n ]\n );\n\n if ($stage === null) {\n $this->importStages(null, $stageId);\n }\n\n if ($stage === null) {\n $this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);\n }\n\n $this->cachedStages[$cacheKey] = $stage;\n\n return $stage;\n }\n\n private function resolveAmount(array $properties): ?string\n {\n $amount = null;\n if (! empty($properties['amount'])) {\n $amount = str_replace(',', '', $properties['amount']);\n }\n\n if ($this->config->hasDefaultCurrencyFieldSet()) {\n $valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();\n $amount = $properties[$valueFieldName] ?? $amount;\n }\n\n return $amount;\n }\n\n private function parseCleanDatetime(string $datetime): ?Carbon\n {\n // Treat pre-1980 values as invalid\n $minValidDate = Carbon::parse('1980-01-01 00:00:00');\n\n try {\n $date = Carbon::parse($datetime);\n\n if ($minValidDate->gt($date)) {\n return null;\n }\n\n return $date;\n } catch (Exception) {\n return null; // On parse error, treat as null\n }\n }\n\n private function resolveDealProbability(?string $stageProbability): int\n {\n if ($stageProbability === null) {\n return 0;\n }\n\n $probability = (float) $stageProbability;\n\n return $probability > 1 ? 0 : (int) ($probability * 100);\n }\n\n private function resolveForecastCategory(?string $forecastCategory): string\n {\n if (! $forecastCategory) {\n return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;\n }\n\n $forecastCategory = str_replace('_', ' ', $forecastCategory);\n\n return ucwords(strtolower($forecastCategory));\n }\n\n private function importExternalFieldData(array $properties, int $opportunityId): void\n {\n $crmFields = $this->getOpportunitySyncableFields();\n $this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);\n }\n\n private function importOpportunityContacts(Opportunity $opportunity, array $associations): void\n {\n // Handle empty or missing contact associations\n if (empty($associations)) {\n // Remove all existing contact associations if none provided\n $this->removeAllOpportunityContacts($opportunity);\n\n return;\n }\n\n // Use differential sync approach for better performance and accuracy\n $this->syncOpportunityContactsDifferential($opportunity, $associations);\n }\n\n /**\n * Sync opportunity contacts using differential approach\n * This compares current vs new associations and only makes necessary changes\n */\n private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void\n {\n $currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);\n $contactAssociationIds = array_keys($contactAssociations);\n\n $contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);\n $contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);\n\n if (empty($contactsToAdd) && empty($contactsToRemove)) {\n return;\n }\n\n $this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);\n\n $this->removeContactAssociations($opportunity, $contactsToRemove);\n $this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);\n }\n\n private function getCurrentContactCrmIds(Opportunity $opportunity): array\n {\n return $opportunity->contacts()\n ->pluck('contacts.crm_provider_id')\n ->toArray();\n }\n\n private function logContactAssociationChanges(\n Opportunity $opportunity,\n array $currentContactCrmIds,\n array $contactAssociations,\n array $contactsToAdd,\n array $contactsToRemove\n ): void {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [\n 'opportunity_id' => $opportunity->getId(),\n 'current_contacts' => $currentContactCrmIds,\n 'new_contacts' => $contactAssociations,\n 'contacts_to_add' => $contactsToAdd,\n 'contacts_to_remove' => $contactsToRemove,\n ]);\n }\n\n private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void\n {\n if (empty($contactsToRemove)) {\n return;\n }\n\n $contactsToDetach = $opportunity->contacts()\n ->whereIn('contacts.crm_provider_id', $contactsToRemove)\n ->pluck('contacts.id')\n ->toArray();\n\n if (! empty($contactsToDetach)) {\n $opportunity->contacts()->detach($contactsToDetach);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_contact_crm_ids' => $contactsToRemove,\n 'removed_contact_count' => count($contactsToDetach),\n ]);\n }\n }\n\n private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void\n {\n if (empty($contactsToAdd)) {\n return;\n }\n\n $contactsAdded = [];\n foreach ($contactsToAdd as $crmId) {\n $id = $contactAssociations[$crmId];\n\n if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {\n $contactsAdded[] = $crmId;\n }\n }\n\n $this->logAddedContacts($opportunity, $contactsAdded);\n }\n\n private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool\n {\n try {\n $contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);\n\n if (! $contact) {\n return false;\n }\n\n return $this->performContactAttachment($opportunity, $contact, $crmId);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [\n 'opportunity_id' => $opportunity->getId(),\n 'contact_crm_id' => $crmId,\n 'error' => $e->getMessage(),\n ]);\n\n return false;\n }\n }\n\n private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool\n {\n try {\n $opportunity->contacts()->attach($contact->getId(), [\n 'crm_provider_id' => $crmId,\n ]);\n\n return true;\n } catch (\\Illuminate\\Database\\QueryException $e) {\n if (str_contains($e->getMessage(), 'Duplicate entry')) {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [\n 'contact_id' => $contact->getId(),\n 'contact_crm_id' => $crmId,\n 'opportunity_id' => $opportunity->getId(),\n ]);\n\n return false;\n }\n\n throw $e;\n }\n }\n\n private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void\n {\n if (! empty($contactsAdded)) {\n $this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'contacts_to_add_count' => count($contactsAdded),\n 'added_contact_crm_ids' => $contactsAdded,\n 'added_contacts_count' => count($contactsAdded),\n ]);\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.049609374,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.008203125,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<template>\n <WelcomeLayout\n title=\"Account disconnected\"\n textPosition=\"center\"\n :icon=\"faUnlink\"\n :class=\"$style.layout\"\n >\n <div :class=\"$style.container\" v-if=\"providersLoaded\">\n <p>\n <strong>\n It looks like your {{ localProvider.displayName }} account has become\n disconnected\n </strong>\n </p>\n <p :class=\"$style.small\">Please re-connect to continue</p>\n <p v-if=\"isInIframe\">\n We'll open the {{ localProvider.displayName }} authentication in a new\n tab. Please return here and refresh the page once complete\n </p>\n\n <GoogleLikeButton\n v-if=\"localProvider.viaIntegrationApp && crmTokenLoaded\"\n as=\"a\"\n :key=\"localProvider.name\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n @click=\"integrationAppOnClick\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n <GoogleLikeButton\n v-if=\"!localProvider.viaIntegrationApp\"\n as=\"a\"\n :key=\"localProvider.name\"\n :href=\"`/auth/redirect/${localProvider.name}`\"\n :target=\"target\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n </div>\n <BuildInfo />\n\n <KioskBanner />\n </WelcomeLayout>\n</template>\n\n<script>\nimport window from \"window\";\nimport axios from \"axios\";\nimport { faUnlink } from \"@fortawesome/pro-regular-svg-icons\";\nimport isInIframe from \"@/utils/isInIframe\";\nimport BuildInfo from \"@/components/layout/BuildInfo/BuildInfo.vue\";\nimport KioskBanner from \"@/components/shared/KioskBanner/KioskBanner.vue\";\nimport WelcomeLayout from \"@/components/layout/WelcomeLayout/WelcomeLayout.vue\";\nimport GoogleLikeButton from \"@/components/shared/Buttons/GoogleLikeButton.vue\";\nimport { showSnackbarError, normalizeError } from \"@/utils/index\";\nimport { IntegrationAppClient } from \"@integration-app/sdk\";\n\nexport default {\n name: \"ConnectPage\",\n components: {\n BuildInfo,\n KioskBanner,\n WelcomeLayout,\n GoogleLikeButton,\n },\n data() {\n return {\n ...window.connectData,\n crmToken: null,\n faUnlink,\n isInIframe,\n providers: [],\n providersLoaded: false,\n crmTokenLoaded: false,\n };\n },\n computed: {\n localProvider() {\n return this.providers.find((e) => e.name === this.provider);\n },\n target() {\n return this.isInIframe ? \"_blank\" : null;\n },\n },\n created() {\n this.getProviders();\n },\n mounted() {\n this.showErrors();\n },\n watch: {\n providersLoaded() {\n if (this.providersLoaded) {\n this.prepareIntegrationAppConnection();\n }\n },\n },\n methods: {\n showErrors() {\n if (!this.error) return;\n\n showSnackbarError(this.error, undefined, undefined, false);\n },\n unwrapEntityResponse({ data }) {\n return data.map(({ icon, name, displayName, viaIntegrationApp }) => {\n return { icon, name, displayName, viaIntegrationApp };\n });\n },\n async getProviders() {\n try {\n const response = await axios.get(\"/api/v1/connect-providers\");\n this.providers = this.unwrapEntityResponse(response);\n this.providersLoaded = true;\n } catch {\n showSnackbarError(\n \"An error occurred, while loading form data (connect providers).\",\n );\n }\n },\n async prepareIntegrationAppConnection() {\n if (this.localProvider.viaIntegrationApp) {\n try {\n const response = await axios.get(\"/api/v1/integration-app-token\");\n this.crmToken = response.data.token;\n this.crmTokenLoaded = true;\n } catch (error) {\n console.log(error);\n showSnackbarError(\n `An error occurred while preparing the page.\n Try refreshing, if the error persists get in touch with the Jiminny team.`,\n );\n }\n }\n },\n async integrationAppOnClick() {\n const integrationApp = new IntegrationAppClient({\n token: this.crmToken,\n });\n\n const connection = await integrationApp\n .integration(this.localProvider.name)\n .openNewConnection({\n showPoweredBy: false,\n allowMultipleConnections: false,\n });\n\n console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));\n\n // [IntegrationApp] openNewConnection resolved: {\n // \"id\":\"69e0b41a67d0068c2ca0b48e\",\n // \"name\":\"Zoho CRM\",\n // \"userId\":\"1ece66c8-feb1-4df1-b321-21607daf4623\",\n // \"tenantId\":\"69e0b3faef3e7b6248189289\",\n // \"isTest\":false,\n // \"connected\":true,\n // \"state\":\"READY\",\n // \"errors\":[],\n // \"integrationId\":\"66fe6c913202f3a165e3c14d\",\n // \"externalAppId\":\"6671653e7e2d642e4e41b0fa\",\n // \"authOptionKey\":\"\",\n // \"createdAt\":\"2026-04-16T10:04:10.420Z\",\n // \"updatedAt\":\"2026-04-16T10:04:10.575Z\",\n // \"retryAttempts\":0,\n // \"isDeactivated\":false\n // }\n\n if (connection && connection.disconnected !== true && connection.connected !== false) {\n console.log('[IntegrationApp] connection condition matched');\n try {\n const saveRequest = await axios.post(\n \"/api/v1/integration-app-connect\",\n );\n if (saveRequest.data && saveRequest.data.success === true) {\n /** If all is good refresh the page here */\n window.location = \"/dashboard\";\n return;\n }\n\n throw new Error(saveRequest.data.message);\n } catch (error) {\n console.log(error);\n showSnackbarError(normalizeError(error));\n }\n }\n },\n },\n};\n</script>\n\n<style module lang=\"less\" src=\"./connect.less\"></style>","depth":4,"value":"<template>\n <WelcomeLayout\n title=\"Account disconnected\"\n textPosition=\"center\"\n :icon=\"faUnlink\"\n :class=\"$style.layout\"\n >\n <div :class=\"$style.container\" v-if=\"providersLoaded\">\n <p>\n <strong>\n It looks like your {{ localProvider.displayName }} account has become\n disconnected\n </strong>\n </p>\n <p :class=\"$style.small\">Please re-connect to continue</p>\n <p v-if=\"isInIframe\">\n We'll open the {{ localProvider.displayName }} authentication in a new\n tab. Please return here and refresh the page once complete\n </p>\n\n <GoogleLikeButton\n v-if=\"localProvider.viaIntegrationApp && crmTokenLoaded\"\n as=\"a\"\n :key=\"localProvider.name\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n @click=\"integrationAppOnClick\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n <GoogleLikeButton\n v-if=\"!localProvider.viaIntegrationApp\"\n as=\"a\"\n :key=\"localProvider.name\"\n :href=\"`/auth/redirect/${localProvider.name}`\"\n :target=\"target\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n </div>\n <BuildInfo />\n\n <KioskBanner />\n </WelcomeLayout>\n</template>\n\n<script>\nimport window from \"window\";\nimport axios from \"axios\";\nimport { faUnlink } from \"@fortawesome/pro-regular-svg-icons\";\nimport isInIframe from \"@/utils/isInIframe\";\nimport BuildInfo from \"@/components/layout/BuildInfo/BuildInfo.vue\";\nimport KioskBanner from \"@/components/shared/KioskBanner/KioskBanner.vue\";\nimport WelcomeLayout from \"@/components/layout/WelcomeLayout/WelcomeLayout.vue\";\nimport GoogleLikeButton from \"@/components/shared/Buttons/GoogleLikeButton.vue\";\nimport { showSnackbarError, normalizeError } from \"@/utils/index\";\nimport { IntegrationAppClient } from \"@integration-app/sdk\";\n\nexport default {\n name: \"ConnectPage\",\n components: {\n BuildInfo,\n KioskBanner,\n WelcomeLayout,\n GoogleLikeButton,\n },\n data() {\n return {\n ...window.connectData,\n crmToken: null,\n faUnlink,\n isInIframe,\n providers: [],\n providersLoaded: false,\n crmTokenLoaded: false,\n };\n },\n computed: {\n localProvider() {\n return this.providers.find((e) => e.name === this.provider);\n },\n target() {\n return this.isInIframe ? \"_blank\" : null;\n },\n },\n created() {\n this.getProviders();\n },\n mounted() {\n this.showErrors();\n },\n watch: {\n providersLoaded() {\n if (this.providersLoaded) {\n this.prepareIntegrationAppConnection();\n }\n },\n },\n methods: {\n showErrors() {\n if (!this.error) return;\n\n showSnackbarError(this.error, undefined, undefined, false);\n },\n unwrapEntityResponse({ data }) {\n return data.map(({ icon, name, displayName, viaIntegrationApp }) => {\n return { icon, name, displayName, viaIntegrationApp };\n });\n },\n async getProviders() {\n try {\n const response = await axios.get(\"/api/v1/connect-providers\");\n this.providers = this.unwrapEntityResponse(response);\n this.providersLoaded = true;\n } catch {\n showSnackbarError(\n \"An error occurred, while loading form data (connect providers).\",\n );\n }\n },\n async prepareIntegrationAppConnection() {\n if (this.localProvider.viaIntegrationApp) {\n try {\n const response = await axios.get(\"/api/v1/integration-app-token\");\n this.crmToken = response.data.token;\n this.crmTokenLoaded = true;\n } catch (error) {\n console.log(error);\n showSnackbarError(\n `An error occurred while preparing the page.\n Try refreshing, if the error persists get in touch with the Jiminny team.`,\n );\n }\n }\n },\n async integrationAppOnClick() {\n const integrationApp = new IntegrationAppClient({\n token: this.crmToken,\n });\n\n const connection = await integrationApp\n .integration(this.localProvider.name)\n .openNewConnection({\n showPoweredBy: false,\n allowMultipleConnections: false,\n });\n\n console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));\n\n // [IntegrationApp] openNewConnection resolved: {\n // \"id\":\"69e0b41a67d0068c2ca0b48e\",\n // \"name\":\"Zoho CRM\",\n // \"userId\":\"1ece66c8-feb1-4df1-b321-21607daf4623\",\n // \"tenantId\":\"69e0b3faef3e7b6248189289\",\n // \"isTest\":false,\n // \"connected\":true,\n // \"state\":\"READY\",\n // \"errors\":[],\n // \"integrationId\":\"66fe6c913202f3a165e3c14d\",\n // \"externalAppId\":\"6671653e7e2d642e4e41b0fa\",\n // \"authOptionKey\":\"\",\n // \"createdAt\":\"2026-04-16T10:04:10.420Z\",\n // \"updatedAt\":\"2026-04-16T10:04:10.575Z\",\n // \"retryAttempts\":0,\n // \"isDeactivated\":false\n // }\n\n if (connection && connection.disconnected !== true && connection.connected !== false) {\n console.log('[IntegrationApp] connection condition matched');\n try {\n const saveRequest = await axios.post(\n \"/api/v1/integration-app-connect\",\n );\n if (saveRequest.data && saveRequest.data.success === true) {\n /** If all is good refresh the page here */\n window.location = \"/dashboard\";\n return;\n }\n\n throw new Error(saveRequest.data.message);\n } catch (error) {\n console.log(error);\n showSnackbarError(normalizeError(error));\n }\n }\n },\n },\n};\n</script>\n\n<style module lang=\"less\" src=\"./connect.less\"></style>","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.0140625,"top":0.041666668,"width":0.028515626,"height":0.021527778},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6089929419086115132
|
-8178086448081891036
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Code changed:
Hide
Sync Changes
Hide This Notification
33
2
19
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use HubSpot\Client\Crm\Deals\Model\CollectionResponseAssociatedId;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\Account;
use Exception;
use Jiminny\Component\DealInsights\Forecast\Forecast;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Contact;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Exceptions\CrmException;
use Jiminny\Models\Opportunity;
use Illuminate\Support\Collection;
use Jiminny\Models\Stage;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Services\Crm\Hubspot\DealFieldsService;
use Jiminny\Services\Crm\Hubspot\OpportunitySyncStrategy\HubspotSingleSyncStrategy;
use Jiminny\Services\Crm\Hubspot\WebhookSyncBatchProcessor;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Utils\CurrencyFormatter;
/**
* Optimized sync methods for better performance
* These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains
*/
trait OpportunitySyncTrait
{
private const int BATCH_SIZE = 100;
private const int BATCH_PROCESS_SIZE = 800;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected DealFieldsService $dealFieldsService;
private ?array $cachedClosedDealStages = null;
private array $cachedBusinessProcesses = [];
private array $cachedStages = [];
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$parameters['config'] = $this->config;
$syncCount = 0;
$reportedTotal = 0;
$lastSyncedId = [];
try {
foreach ($strategies as $strategyName => $syncStrategy) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .
$strategyName
);
$total = 0;
$lastId = null;
$buffer = [];
// HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies
foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {
$buffer[] = $hsOpportunity;
// process every 800 rows (fits < 1 000 association limit)
if (\count($buffer) >= self::BATCH_PROCESS_SIZE) {
$syncCount += $this->processOpportunityBatch($buffer);
$buffer = [];
}
}
// leftovers
if ($buffer) {
$syncCount += $this->processOpportunityBatch($buffer);
}
$reportedTotal += $total;
$lastSyncedId = $lastId;
}
} catch (\HubSpot\Client\Crm\Deals\ApiException | CrmException $e) {
$this->handleSyncException($e, $parameters);
}
$this->logger->info(
'[HubSpot] Synced opportunities',
[
'team' => $this->team->getId(),
'sync_count' => $syncCount,
'total' => $reportedTotal,
'last_synced_id' => $lastSyncedId,
]
);
return $reportedTotal;
}
private function handleSyncException(\Throwable $e, array $parameters): void
{
if (($parameters['since'] ?? null) instanceof Carbon) {
$parameters['since'] = $parameters['since']->toDateTimeString();
}
$parameters['config'] = $this->config->getId();
$this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [
'teamId' => $this->team->getUuid(),
'parameters' => $parameters,
'reason' => $e->getMessage(),
]);
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,
);
$parameters = [
'config' => $this->config,
'crm_id' => $crmId,
];
try {
if (! $strategy instanceof HubspotSingleSyncStrategy) {
throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');
}
$hsOpportunity = $strategy->fetchOpportunity($parameters);
} catch (\HubSpot\Client\Crm\Deals\ApiException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->getUuid(),
'crmId' => $crmId,
'reason' => $e->getMessage(),
]);
return null;
}
$hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);
return $this->importOrUpdateOpportunity($hsOpportunity);
}
/**
* Process webhook-collected opportunity batches.
*
* Drains Redis sets containing company CRM IDs collected from webhook events
* and dispatches ImportOpportunityBatch jobs for batch processing.
*
* @return int Number of opportunity IDs dispatched to jobs
*/
public function batchSyncOpportunities(): int
{
$configId = $this->team->getCrmConfiguration()->getId();
return $this->batchProcessor->processBatchesForObjectType(
WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,
$configId
);
}
/**
* Import a batch of opportunities by their CRM IDs.
* Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().
*
* @param array<string> $crmIds HubSpot deal CRM IDs
*
* @return array{success: array, failed_ids: array, errors?: array<string, string>}
*/
public function importOpportunityBatchByIds(array $crmIds): array
{
$fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);
$allDeals = [];
foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {
$deals = $this->client->getOpportunitiesByIds($chunk, $fields);
foreach ($deals as $deal) {
$allDeals[] = $deal;
}
}
// IDs not returned by HubSpot are likely deleted or inaccessible deals.
// These are not failures — retrying won't bring them back.
$fetchedIds = array_map('strval', array_column($allDeals, 'id'));
$notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));
if (! empty($notFoundIds)) {
$this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [
'teamId' => $this->team->getId(),
'notFoundCount' => \count($notFoundIds),
'notFoundIds' => $notFoundIds,
'requestedCount' => \count($crmIds),
'fetchedCount' => \count($allDeals),
]);
}
if (empty($allDeals)) {
return ['success' => [], 'failed_ids' => []];
}
return $this->importOpportunityBatch($allDeals);
}
private function getClosedDealStages(): array
{
if ($this->cachedClosedDealStages !== null) {
return $this->cachedClosedDealStages;
}
$stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);
$data = [
'lost' => [],
'won' => [],
];
foreach ($stages as $stage) {
if ($stage->probability == 0.00) {
$data['lost'][] = $stage->crm_provider_id;
}
if ($stage->probability == 100.00) {
$data['won'][] = $stage->crm_provider_id;
}
}
$this->cachedClosedDealStages = $data;
return $data;
}
/**
* Import deals into the database with pre-fetched associations.
*
* API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT
* caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()
* where Laravel retries the whole job with backoff. After all retries exhausted,
* failed() requeues all IDs to Redis.
*
* The per-deal loop catches exceptions individually. A deal can end up in three states:
* - success: imported/updated successfully
* - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)
* These are permanent issues — retrying won't fix them.
* - skipped (null): missing dependencies (no account, unknown pipeline/stage).
* This is acceptable — the deal cannot be imported until those exist.
*/
private function importOpportunityBatch(array $deals): array
{
$syncedOpportunities = [
'success' => [],
'failed_ids' => [],
];
$dealIds = array_column($deals, 'id');
// Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the
// queue job retries the whole batch and eventually requeues all deal IDs back to Redis.
try {
$companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');
$contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');
$associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);
$existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(
$this->config,
array_map('strval', $dealIds)
);
$existingCrmIdSet = array_flip($existingCrmIds);
} catch (\Throwable $e) {
$this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [
'teamId' => $this->team->getId(),
'dealCount' => count($dealIds),
'error' => $e->getMessage(),
]);
throw $e;
}
foreach ($deals as $deal) {
try {
$deal['associations'] = $this->prepareAssociationsForOpportunity(
$deal['id'],
$companyAssociations,
$contactAssociations,
$associationsData
);
$syncedOpportunity = $this->importOrUpdateOpportunity(
$deal,
isset($existingCrmIdSet[(string) $deal['id']])
);
if ($syncedOpportunity) {
$syncedOpportunities['success'][] = $syncedOpportunity;
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [
'teamId' => $this->team->getId(),
'crmId' => $deal['id'],
'error' => $e->getMessage(),
]);
$syncedOpportunities['failed_ids'][] = $deal['id'];
$syncedOpportunities['errors'][$deal['id']] = $e->getMessage();
}
}
return $syncedOpportunities;
}
/**
* Prepare associated entities for opportunities with optimized batch processing
* Returns structured data with CRM ID to DB ID mappings for each opportunity
*/
private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array
{
// Step 1: Collect all unique company and contact IDs from associations
$allCompanyIds = $this->flattenAssociationIds($companyAssociations);
$allContactIds = $this->flattenAssociationIds($contactAssociations);
// Step 2: Batch sync missing entities and get CRM ID to DB ID mappings
$companyIdMappings = [];
$contactIdMappings = [];
if (! empty($allCompanyIds)) {
$companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);
}
if (! empty($allContactIds)) {
$contactIdMappings = $this->prepareAssociatedContacts($allContactIds);
}
return [
'company_id_mappings' => $companyIdMappings,
'contact_id_mappings' => $contactIdMappings,
];
}
/**
* Flatten association data to get unique IDs
*/
private function flattenAssociationIds(array $associations): array
{
$ids = [];
foreach ($associations as $dealAssociations) {
if (is_array($dealAssociations)) {
foreach ($dealAssociations as $id) {
$ids[$id] = true;
}
}
}
return array_keys($ids);
}
/**
* Batch sync missing accounts
*/
private function prepareAssociatedAccounts(array $companyIds): array
{
// Find which accounts already exist
$existingAccounts = $this->crmEntityRepository
->findAccountsByExternalIds($this->config, $companyIds);
$existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();
$existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {
return [$account->getCrmProviderId() => $account->getId()];
})->toArray();
$missingCompanyIds = array_diff($companyIds, $existingCompanyIds);
if (empty($missingCompanyIds)) {
return $existingAccountsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [
'teamId' => $this->team->getUuid(),
'total_companies' => count($companyIds),
'existing_companies' => count($existingCompanyIds),
'missing_companies' => count($missingCompanyIds),
]);
// we already have limit on opportunity ids count
// Initialize variable before try block
$syncedAccountsData = [];
try {
$syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [
'size' => count($missingCompanyIds),
'error' => $e->getMessage(),
]);
$syncedAccountsData = [];
}
return $existingAccountsData + $syncedAccountsData;
}
/**
* Prepare associated contacts - find existing and sync missing ones
* Returns mapping of CRM ID to DB ID
*/
private function prepareAssociatedContacts(array $contactIds): array
{
// Find which contacts already exist
$existingContacts = $this->crmEntityRepository
->findContactsByExternalIds($this->config, $contactIds);
$existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();
// Create mapping for existing contacts
$existingContactsData = $existingContacts->mapWithKeys(function ($contact) {
return [$contact->getCrmProviderId() => $contact->getId()];
})->toArray();
$missingContactIds = array_diff($contactIds, $existingContactIds);
if (empty($missingContactIds)) {
return $existingContactsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [
'teamId' => $this->team->getUuid(),
'total_contacts' => count($contactIds),
'existing_contacts' => count($existingContactIds),
'missing_contacts' => count($missingContactIds),
]);
// Sync missing contacts using batch API
try {
$syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [
'size' => count($missingContactIds),
'error' => $e->getMessage(),
]);
$syncedContactsData = [];
}
return $existingContactsData + $syncedContactsData;
}
private function batchSyncCrmObjects(string $objectType, array $crmIds): array
{
$syncObjects = [];
$crmObjectIds = array_values($crmIds);
foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {
try {
$objects = $objectType === 'companies' ?
$this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :
$this->client->getContactsByIds($chunk, $this->getContactFields());
foreach ($objects as $objectId => $objectData) {
$this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [
'requested_count' => count($chunk),
'synced_count' => count($objects),
]);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [
'ids' => $chunk,
'error' => $e->getMessage(),
]);
}
}
return $syncObjects;
}
private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void
{
try {
$object = $objectType === 'companies' ?
$this->importAccount($objectData) :
$this->importContact($objectData);
if ($object) {
$syncObjects[$object->getCrmProviderId()] = $object->getId();
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [
'id' => $objectId,
'error' => $e->getMessage(),
]);
}
}
/**
* Prepare associations for a single opportunity
*
* The return value is an array with the following structure:
* [
* 'companies' => [
* $companyCrmId => $companyId,
* ...
* ],
* 'contacts' => [
* $contactCrmId => $contactId,
* ...
* ],
* 'account_id' => $accountId,
* ]
*/
private function prepareAssociationsForOpportunity(
string $oppCrmId,
array $companyAssociations,
array $contactAssociations,
array $associationsData
): array {
$associations = [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
$oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];
foreach ($oppCompanyIds as $companyCrmId) {
if (isset($associationsData['company_id_mappings'][$companyCrmId])) {
$associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];
// Set primary account (first company becomes primary account)
if ($associations['account_id'] === null) {
$associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];
}
}
}
$oppContactIds = $contactAssociations[$oppCrmId] ?? [];
foreach ($oppContactIds as $contactCrmId) {
if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {
$associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];
}
}
return $associations;
}
/**
* Update only associations for an opportunity
*/
private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void
{
// Update contact associations
$this->importOpportunityContacts($opportunity, $associations['contacts']);
// Update company (account) associations
$this->updateOpportunityAccount($opportunity, $associations['account_id']);
}
/**
* Remove all contact associations from an opportunity
*/
private function removeAllOpportunityContacts(Opportunity $opportunity): void
{
$currentCount = (int) $opportunity->contacts()->count();
if ($currentCount > 0) {
$opportunity->contacts()->detach();
$this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_count' => $currentCount,
]);
}
}
private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void
{
if ($accountId === null) {
// No account ID provided - keep current account
return;
}
$currentAccountId = $opportunity->getAccountId();
// Only update if account has changed
if ($currentAccountId !== $accountId) {
$opportunity->account_id = $accountId;
$opportunity->save();
$this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [
'opportunity_id' => $opportunity->getId(),
'old_account_id' => $currentAccountId,
'new_account_id' => $accountId,
]);
}
}
/**
* Find existing opportunities by external IDs (OPTIMIZED VERSION)
* Uses batch query for better performance
*/
private function findExistingOpportunities(array $crmIds): Collection
{
return $this->crmEntityRepository
->findOpportunitiesByExternalIds($this->config, $crmIds);
}
private function processOpportunityBatch(array $opportunities): int
{
$syncedOpportunities = $this->importOpportunityBatch($opportunities);
return count($syncedOpportunities['success'] ?? []);
}
/**
* Convert single deal associations from HubSpot format to internal format
* Handles both HubSpot SDK objects and array formats
*
* @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed
*
* @return array Processed associations with DB IDs
*/
private function convertDealAssociations(array $opportunityAssociations): array
{
$associations = $this->initializeAssociationsStructure();
if (empty($opportunityAssociations)) {
return $associations;
}
$associationIds = $this->extractAssociationIds($opportunityAssociations);
$this->processCompanyAssociations($associationIds, $associations);
$this->processContactAssociations($associationIds, $associations);
return $associations;
}
private function initializeAssociationsStructure(): array
{
return [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
}
private function extractAssociationIds(array $opportunityAssociations): array
{
$associationIds = [];
foreach ($opportunityAssociations as $type => $associationData) {
if (! empty($associationData)) {
$associationIds[$type] = $this->convertSingleDealAssociations($associationData);
}
}
return $associationIds;
}
private function processCompanyAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['companies'])) {
return;
}
$companyId = $associationIds['companies'][0];
$account = $this->findOrSyncAccount($companyId);
if ($account instanceof Account) {
$associations['companies'][$companyId] = $account->getId();
$associations['account_id'] = $account->getId();
}
}
private function processContactAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['contacts'])) {
return;
}
foreach ($associationIds['contacts'] as $contactId) {
$contact = $this->findOrSyncContact($contactId);
if ($contact instanceof Contact) {
$associations['contacts'][$contactId] = $contact->getId();
}
}
}
private function findOrSyncAccount(string $companyId): ?Account
{
$account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);
if (! $account instanceof Account) {
$account = $this->syncAccount($companyId);
}
return $account;
}
private function findOrSyncContact(string $contactId): ?Contact
{
$contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);
if (! $contact instanceof Contact) {
$contact = $this->syncContact($contactId);
}
return $contact;
}
private function convertSingleDealAssociations($opportunityAssociations = null): array
{
$associationData = [];
if ($opportunityAssociations === null) {
return $associationData;
}
// Handle array input (from extractAssociationIds)
if (is_array($opportunityAssociations)) {
return $opportunityAssociations;
}
// Handle CollectionResponseAssociatedId object
if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {
foreach ($opportunityAssociations->getResults() as $association) {
$associationData[] = $association->getId();
}
}
return $associationData;
}
private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity
{
if (empty($crmData['properties'])) {
return null;
}
$crmId = (string) $crmData['id'];
$properties = $crmData['properties'];
$associations = $crmData['associations'] ?? [];
$opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(
$this->config,
$crmId
);
if ($opportunityExists) {
return $this->updateOpportunity($crmId, $properties, $associations);
} else {
return $this->createOpportunity($crmId, $properties, $associations);
}
}
/**
* Create new opportunity
*/
private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity
{
$accountId = $this->resolveAccountId($associations);
if (! $accountId) {
return null;
}
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
if (! $businessProcess) {
return null;
}
$stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);
if (! $stage) {
return null;
}
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->importOpportunityContacts($opportunity, $associations['contacts']);
if ($opportunity->wasRecentlyCreated) {
MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());
}
return $opportunity;
}
/**
* Update existing opportunity
*/
private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity
{
$accountId = $this->resolveAccountId($associations);
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
$stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->updateOpportunityAssociations($opportunity, $associations);
return $opportunity;
}
private function resolveAccountId(array $associations): ?int
{
if (! empty($associations['accountId'])) {
return $associations['accountId'];
}
if (empty($associations)) {
return null;
}
// we can't resolve multiple account ids (currently SDK returns one company)
foreach ($associations['companies'] as $accountId) {
return $accountId;
}
return null;
}
private function buildOpportunityData(
array $properties,
?int $accountId,
?BusinessProcess $businessProcess,
?Stage $stage
): array {
$ownerId = null;
$profile = null;
if (! empty($properties['hubspot_owner_id'])) {
$ownerId = $properties['hubspot_owner_id'];
$profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);
}
$name = 'Unknown';
if (isset($properties['dealname'])) {
$name = mb_strimwidth($properties['dealname'], 0, 128);
}
$amount = $this->resolveAmount($properties);
$currency = $properties['deal_currency_code'] ?? null;
$closeDate = null;
if (! empty($properties['closedate'])) {
$closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');
}
$remotelyCreatedAt = null;
if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {
$date = $this->parseCleanDatetime($properties['createdate']);
$remotelyCreatedAt = $date?->format('Y-m-d H:i:s');
}
$closedStages = $this->getClosedDealStages();
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$data = [
'team_id' => $this->team->getId(),
'user_id' => $profile ? $profile->user_id : null,
'owner_id' => $ownerId,
'name' => $name,
'value' => ! empty($amount) ? $amount : null,
'currency_code' => CurrencyFormatter::formatCode($currency),
'close_date' => $closeDate,
'is_closed' => $isWon || $isLost,
'is_won' => $isWon,
'remotely_created_at' => $remotelyCreatedAt,
'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),
'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),
];
if ($accountId) {
$data['account_id'] = $accountId;
}
if ($stage) {
$data['stage_id'] = $stage->id;
}
if ($businessProcess) {
$recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);
if ($recordType) {
$data['record_type_id'] = $recordType->id;
}
}
return $data;
}
private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess
{
if ($pipelineId === null) {
return null;
}
if (isset($this->cachedBusinessProcesses[$pipelineId])) {
return $this->cachedBusinessProcesses[$pipelineId];
}
$businessProcess = $this->getBusinessProcess($pipelineId);
if (! $businessProcess instanceof BusinessProcess) {
$this->importStages();
$businessProcess = $this->getBusinessProcess($pipelineId);
}
if (! $businessProcess instanceof BusinessProcess) {
$this->logger->info(
'[HubSpot] Deal is not attached to a pipeline',
[
'pipeline' => $pipelineId]
);
}
$this->cachedBusinessProcesses[$pipelineId] = $businessProcess;
return $businessProcess;
}
private function getBusinessProcess(string $pipelineId): ?BusinessProcess
{
return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);
}
private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage
{
if (empty($stageId)) {
return null;
}
$cacheKey = $businessProcess->getId() . ':' . $stageId;
if (isset($this->cachedStages[$cacheKey])) {
return $this->cachedStages[$cacheKey];
}
$stage = $this->crmEntityRepository->getPipelineStageByConditions(
$businessProcess,
[
'crm_provider_id' => $stageId,
'type' => Stage::TYPE_OPPORTUNITY,
]
);
if ($stage === null) {
$this->importStages(null, $stageId);
}
if ($stage === null) {
$this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);
}
$this->cachedStages[$cacheKey] = $stage;
return $stage;
}
private function resolveAmount(array $properties): ?string
{
$amount = null;
if (! empty($properties['amount'])) {
$amount = str_replace(',', '', $properties['amount']);
}
if ($this->config->hasDefaultCurrencyFieldSet()) {
$valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();
$amount = $properties[$valueFieldName] ?? $amount;
}
return $amount;
}
private function parseCleanDatetime(string $datetime): ?Carbon
{
// Treat pre-1980 values as invalid
$minValidDate = Carbon::parse('1980-01-01 00:00:00');
try {
$date = Carbon::parse($datetime);
if ($minValidDate->gt($date)) {
return null;
}
return $date;
} catch (Exception) {
return null; // On parse error, treat as null
}
}
private function resolveDealProbability(?string $stageProbability): int
{
if ($stageProbability === null) {
return 0;
}
$probability = (float) $stageProbability;
return $probability > 1 ? 0 : (int) ($probability * 100);
}
private function resolveForecastCategory(?string $forecastCategory): string
{
if (! $forecastCategory) {
return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;
}
$forecastCategory = str_replace('_', ' ', $forecastCategory);
return ucwords(strtolower($forecastCategory));
}
private function importExternalFieldData(array $properties, int $opportunityId): void
{
$crmFields = $this->getOpportunitySyncableFields();
$this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);
}
private function importOpportunityContacts(Opportunity $opportunity, array $associations): void
{
// Handle empty or missing contact associations
if (empty($associations)) {
// Remove all existing contact associations if none provided
$this->removeAllOpportunityContacts($opportunity);
return;
}
// Use differential sync approach for better performance and accuracy
$this->syncOpportunityContactsDifferential($opportunity, $associations);
}
/**
* Sync opportunity contacts using differential approach
* This compares current vs new associations and only makes necessary changes
*/
private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void
{
$currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);
$contactAssociationIds = array_keys($contactAssociations);
$contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);
$contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);
if (empty($contactsToAdd) && empty($contactsToRemove)) {
return;
}
$this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);
$this->removeContactAssociations($opportunity, $contactsToRemove);
$this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);
}
private function getCurrentContactCrmIds(Opportunity $opportunity): array
{
return $opportunity->contacts()
->pluck('contacts.crm_provider_id')
->toArray();
}
private function logContactAssociationChanges(
Opportunity $opportunity,
array $currentContactCrmIds,
array $contactAssociations,
array $contactsToAdd,
array $contactsToRemove
): void {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [
'opportunity_id' => $opportunity->getId(),
'current_contacts' => $currentContactCrmIds,
'new_contacts' => $contactAssociations,
'contacts_to_add' => $contactsToAdd,
'contacts_to_remove' => $contactsToRemove,
]);
}
private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void
{
if (empty($contactsToRemove)) {
return;
}
$contactsToDetach = $opportunity->contacts()
->whereIn('contacts.crm_provider_id', $contactsToRemove)
->pluck('contacts.id')
->toArray();
if (! empty($contactsToDetach)) {
$opportunity->contacts()->detach($contactsToDetach);
$this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_contact_crm_ids' => $contactsToRemove,
'removed_contact_count' => count($contactsToDetach),
]);
}
}
private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void
{
if (empty($contactsToAdd)) {
return;
}
$contactsAdded = [];
foreach ($contactsToAdd as $crmId) {
$id = $contactAssociations[$crmId];
if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {
$contactsAdded[] = $crmId;
}
}
$this->logAddedContacts($opportunity, $contactsAdded);
}
private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool
{
try {
$contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);
if (! $contact) {
return false;
}
return $this->performContactAttachment($opportunity, $contact, $crmId);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [
'opportunity_id' => $opportunity->getId(),
'contact_crm_id' => $crmId,
'error' => $e->getMessage(),
]);
return false;
}
}
private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool
{
try {
$opportunity->contacts()->attach($contact->getId(), [
'crm_provider_id' => $crmId,
]);
return true;
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [
'contact_id' => $contact->getId(),
'contact_crm_id' => $crmId,
'opportunity_id' => $opportunity->getId(),
]);
return false;
}
throw $e;
}
}
private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void
{
if (! empty($contactsAdded)) {
$this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [
'opportunity_id' => $opportunity->getId(),
'contacts_to_add_count' => count($contactsAdded),
'added_contact_crm_ids' => $contactsAdded,
'added_contacts_count' => count($contactsAdded),
]);
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<template>
<WelcomeLayout
title="Account disconnected"
textPosition="center"
:icon="faUnlink"
:class="$style.layout"
>
<div :class="$style.container" v-if="providersLoaded">
<p>
<strong>
It looks like your {{ localProvider.displayName }} account has become
disconnected
</strong>
</p>
<p :class="$style.small">Please re-connect to continue</p>
<p v-if="isInIframe">
We'll open the {{ localProvider.displayName }} authentication in a new
tab. Please return here and refresh the page once complete
</p>
<GoogleLikeButton
v-if="localProvider.viaIntegrationApp && crmTokenLoaded"
as="a"
:key="localProvider.name"
:brand-logo="localProvider.name"
:class="$style.connectButton"
@click="integrationAppOnClick"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
<GoogleLikeButton
v-if="!localProvider.viaIntegrationApp"
as="a"
:key="localProvider.name"
:href="`/auth/redirect/${localProvider.name}`"
:target="target"
:brand-logo="localProvider.name"
:class="$style.connectButton"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
</div>
<BuildInfo />
<KioskBanner />
</WelcomeLayout>
</template>
<script>
import window from "window";
import axios from "axios";
import { faUnlink } from "@fortawesome/pro-regular-svg-icons";
import isInIframe from "@/utils/isInIframe";
import BuildInfo from "@/components/layout/BuildInfo/BuildInfo.vue";
import KioskBanner from "@/components/shared/KioskBanner/KioskBanner.vue";
import WelcomeLayout from "@/components/layout/WelcomeLayout/WelcomeLayout.vue";
import GoogleLikeButton from "@/components/shared/Buttons/GoogleLikeButton.vue";
import { showSnackbarError, normalizeError } from "@/utils/index";
import { IntegrationAppClient } from "@integration-app/sdk";
export default {
name: "ConnectPage",
components: {
BuildInfo,
KioskBanner,
WelcomeLayout,
GoogleLikeButton,
},
data() {
return {
...window.connectData,
crmToken: null,
faUnlink,
isInIframe,
providers: [],
providersLoaded: false,
crmTokenLoaded: false,
};
},
computed: {
localProvider() {
return this.providers.find((e) => e.name === this.provider);
},
target() {
return this.isInIframe ? "_blank" : null;
},
},
created() {
this.getProviders();
},
mounted() {
this.showErrors();
},
watch: {
providersLoaded() {
if (this.providersLoaded) {
this.prepareIntegrationAppConnection();
}
},
},
methods: {
showErrors() {
if (!this.error) return;
showSnackbarError(this.error, undefined, undefined, false);
},
unwrapEntityResponse({ data }) {
return data.map(({ icon, name, displayName, viaIntegrationApp }) => {
return { icon, name, displayName, viaIntegrationApp };
});
},
async getProviders() {
try {
const response = await axios.get("/api/v1/connect-providers");
this.providers = this.unwrapEntityResponse(response);
this.providersLoaded = true;
} catch {
showSnackbarError(
"An error occurred, while loading form data (connect providers).",
);
}
},
async prepareIntegrationAppConnection() {
if (this.localProvider.viaIntegrationApp) {
try {
const response = await axios.get("/api/v1/integration-app-token");
this.crmToken = response.data.token;
this.crmTokenLoaded = true;
} catch (error) {
console.log(error);
showSnackbarError(
`An error occurred while preparing the page.
Try refreshing, if the error persists get in touch with the Jiminny team.`,
);
}
}
},
async integrationAppOnClick() {
const integrationApp = new IntegrationAppClient({
token: this.crmToken,
});
const connection = await integrationApp
.integration(this.localProvider.name)
.openNewConnection({
showPoweredBy: false,
allowMultipleConnections: false,
});
console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));
// [IntegrationApp] openNewConnection resolved: {
// "id":"69e0b41a67d0068c2ca0b48e",
// "name":"Zoho CRM",
// "userId":"1ece66c8-feb1-4df1-b321-21607daf4623",
// "tenantId":"69e0b3faef3e7b6248189289",
// "isTest":false,
// "connected":true,
// "state":"READY",
// "errors":[],
// "integrationId":"66fe6c913202f3a165e3c14d",
// "externalAppId":"6671653e7e2d642e4e41b0fa",
// "authOptionKey":"",
// "createdAt":"2026-04-16T10:04:10.420Z",
// "updatedAt":"2026-04-16T10:04:10.575Z",
// "retryAttempts":0,
// "isDeactivated":false
// }
if (connection && connection.disconnected !== true && connection.connected !== false) {
console.log('[IntegrationApp] connection condition matched');
try {
const saveRequest = await axios.post(
"/api/v1/integration-app-connect",
);
if (saveRequest.data && saveRequest.data.success === true) {
/** If all is good refresh the page here */
window.location = "/dashboard";
return;
}
throw new Error(saveRequest.data.message);
} catch (error) {
console.log(error);
showSnackbarError(normalizeError(error));
}
}
},
},
};
</script>
<style module lang="less" src="./connect.less"></style>
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
46365
|
|
46470
|
NULL
|
0
|
2026-04-17T10:36:37.925635+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422197925_m1.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelp>0 l4lSupport Daily - in 1h 24 m100% <47-zshAPP (-zsh)|X4-zshDOCKER881DEV (-zsh)APP (-zsh)X3./public/vue-assets/assets/ondemand-CE8XLH98.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-3DSxnTNQ.js:./public/vue-assets/assets/AskAnything-BQ36E0GS.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CqCXZwrk.js./public/vue-assets/assets/deal-view-B92qaj32.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-u3UeUUz5.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js•/public/vue-assets/assets/onboard-CCnYJmCP.js./public/vue-assets/assets/StatusBadge-CNGFZm8P.js./public/vue-assets/assets/kiosk-D6N5-ivP.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-jlkz65MZ.js../public/vue-assets/assets/ListView-DmKqYVi1.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-BWoBIPKA.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-icPKypZa.js:./public/vue-assets/assets/OrgSettingsLayout-BZ-JOgiH.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-DKsqp_al.js./public/vue-assets/assets/index.module-Bjlhgfd1.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js:./public/vue-assets/assets/team-insights-D9P6ojjD.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-DWumv-QD.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-DiEs6xIb.js:./public/vue-assets/assets/logged-in-layout-Cq1ztH50.jsH8526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kB120.67kB128.71kB129.28 kB133.44kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43kB689.63kB825.23 kB1,402.70 kB[plugin builtin:vite-reporter](!) Somechunks are larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] ₴8APP...
|
NULL
|
-7952806826740830795
|
NULL
|
click
|
ocr
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelp>0 l4lSupport Daily - in 1h 24 m100% <47-zshAPP (-zsh)|X4-zshDOCKER881DEV (-zsh)APP (-zsh)X3./public/vue-assets/assets/ondemand-CE8XLH98.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-3DSxnTNQ.js:./public/vue-assets/assets/AskAnything-BQ36E0GS.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CqCXZwrk.js./public/vue-assets/assets/deal-view-B92qaj32.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-u3UeUUz5.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js•/public/vue-assets/assets/onboard-CCnYJmCP.js./public/vue-assets/assets/StatusBadge-CNGFZm8P.js./public/vue-assets/assets/kiosk-D6N5-ivP.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-jlkz65MZ.js../public/vue-assets/assets/ListView-DmKqYVi1.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-BWoBIPKA.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-icPKypZa.js:./public/vue-assets/assets/OrgSettingsLayout-BZ-JOgiH.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-DKsqp_al.js./public/vue-assets/assets/index.module-Bjlhgfd1.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js:./public/vue-assets/assets/team-insights-D9P6ojjD.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-DWumv-QD.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-DiEs6xIb.js:./public/vue-assets/assets/logged-in-layout-Cq1ztH50.jsH8526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kB120.67kB128.71kB129.28 kB133.44kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43kB689.63kB825.23 kB1,402.70 kB[plugin builtin:vite-reporter](!) Somechunks are larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] ₴8APP...
|
46468
|
|
46471
|
NULL
|
0
|
2026-04-17T10:36:37.901077+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422197901_m2.jpg...
|
PhpStorm
|
faVsco.js – ~/jiminny/app/front-end/src/components faVsco.js – ~/jiminny/app/front-end/src/components/connect/connect.vue...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.03046875,"top":0.017361112,"width":0.0453125,"height":0.022222223},"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"bounds":{"left":0.07578125,"top":0.017361112,"width":0.15898438,"height":0.022222223},"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.78515625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"bounds":{"left":0.803125,"top":0.017361112,"width":0.09765625,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9007813,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9140625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9273437,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96015626,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9734375,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9867188,"top":0.017361112,"width":0.013281226,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.12382813,"top":0.22083333,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.13867188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"bounds":{"left":0.1515625,"top":0.22013889,"width":0.0515625,"height":0.013888889},"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.21367188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.22539063,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.23554687,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.24570313,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5574872765237312613
|
-7735694548458591292
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
PhpStormFileFditViewNavigateCodelaravelRetactonRunToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY] v>W testsU connect.lessV connect.vuedashboardW DeallnsightsD errorPages_ export-portalextension-installledinvitationvonconterenceWa VoUT_ LiveCoach_ Lockedlogin_ MeetingConsent_ mobilel onboardl•__mocks_•U_tests_V MobileAppDownk1 Onboard.lessVenhoard vilPC AutomatedReportsService.phpC) SendReportJob.phpC SendReportMailJob.phpC ReportController.phpTokenBuilder.phpc leamsetuocontroller.onppnp apl.ono© Filesystem.php© Team.php© CreateHeldActivityEvent.phpC) TrackProviderInstalledEvent.phpC RequestGenerateReportJob.phpOpportunitySyncTrait.phpC Opportunity.phpT InteractsWithPivotTable.phgOpoorunityupdated.oneOpportunitystageupdatea.pnpc) FventService?rovider.onmonoortunitvPendingAiAnalvsisatterstadechanded.omC RunOpportunityAiAnalysis.phpC ProcessAlAutomationAnalysiskesults.ong© ImportOpportunityBatch.phpTImportBatchJobTrait.php(C) Service.phpcachedStagesCc W.*trait upportunitysynctraitA33 V2 V1910181028private function resolveForecastCategory(?string $forecastCategory): stringf=1482 usages150private function importExternalFieldData(array $properties, int $opportunityid110501033$crmFields = $this->getOpportunitySyncableFields:Sthis->inportOpportunitvCrmFieldDataSproperties. ScrmFields.Sopportunitx154$155-1501034(aJ Outputini # 1695 X2 rowsvIX. AutovДQMAФW expires Y÷Irefresh token expires Yo_provider y1776336176<null> googleICIsImtpZC1617VmNWFhZGFkLTQwZDktNDLkNy04ZW12LTAzNmNLM.1729613615<null> zoom-phone= custom.loc= aravel.logc SF liminny@localhostC scratch 1.isonconnect.vue XV Onboard.vue< Hs local liminnyalocalnost4 console [EUlC CrmEntityRepository.pho(iii) crm configurations [EU]¿ console IPROD¿ consoe STAGINGII<script>101138methods:async integrationApp0nClickO{cons connecron = avalt unteoraronAodnteoramonuuns. locaurrovloer.naley.openNewConnectiongshowPoweredBy: false.allowMultipleConnections: falser.catch((err) => %console.LoglIntegrationApp openNewconnection rejected:', err):return null;7):all to Lascade, al to commandconsole.log('[IntegrationApp] openNewConnection resolved:'.wsun.scrinontyconnectlonoanex Relec File nae+ 2 of 2 files →loblSupport Daily • in 1h 24 mA100% [z7Fri 17 Apr 13:36:37AutomatedRenortsCommandTestCascadeAutomated Renort RetDebugging OpportuniUpdate Connection Loratner than resolving with a nul/disconnectea connection ob ect as it dla berore.To contirm. add a catch." isconst connection = awalt intedratlonaoointegration(this. Loca(Provider.name)onenNewconnectionshowPoweredBy: talse,allowMultipleConnections: false,}).catch((err) => 1console. loo untegrationApp openNewlonneccion relected: err;return nultLtlles with changesfront-end/src/components/connect/Jconnect.vue +2 -3tront-eno/src/componenis/onboarconooara.vue +l -2ASk anyinind dtl+ &CodeClaude Sonnet 4.6WServicesv _ DatabaseVdEUa console 1 s 59 msua crm_contigurations 1s 391 msd jiminny@localhost4SFd moocallV APROD< console ls o0o msV L STAGINGd console• Dockero_stateytul-rerreshfull-refreshIauth scope Yopenid https://www.googleap1s.com/auth/userinfo.prof1le https://www.googleap1s.com/auth/calendar http..phone:read:admin user:read:adminView allliReject allAccept allOJCSV.L+OgI retry after YIn crea12026-0.<null>2024-11Shortcuts conflicts: Clone Caret Above and 1 more shortcut conflict with macOS shortcuts. Modify these shortcuts or change macOS system settings. // Modify Shortcuts // Don't Show Again (today 12:22W Windsurf Teams 152:1 V UTF-8fh 2 spaces...
|
NULL
|
|
46472
|
981
|
0
|
2026-04-17T10:37:09.318979+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422229318_m1.jpg...
|
PhpStorm
|
faVsco.js – ~/jiminny/app/front-end/src/components faVsco.js – ~/jiminny/app/front-end/src/components/connect/connect.vue...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6433419640701390788
|
-7772847050790327996
|
idle
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
iTerm2ShellEditViewSessionScriptsProfilesWindowHelpldal• Support Daily - in 1h 23 ml100% <47-zshAPP (-zsh)|X4-zshDOCKER2- 881DEV (-zsh)APP (-zsh)X3./public/vue-assets/assets/ondemand-CE8XLH98.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-3DSxnTNQ.js:./public/vue-assets/assets/AskAnything-BQ36E0GS.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CqCXZwrk.js./public/vue-assets/assets/deal-view-B92qaj32.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-u3UeUUz5.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js•/public/vue-assets/assets/onboard-CCnYJmCP.js./public/vue-assets/assets/StatusBadge-CNGFZm8P.js./public/vue-assets/assets/kiosk-D6N5-ivP.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-jlkz65MZ.js../public/vue-assets/assets/ListView-DmKqYVi1.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-BWoBIPKA.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-icPKypZa.js:./public/vue-assets/assets/OrgSettingsLayout-BZ-JOgiH.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-DKsqp_al.js./public/vue-assets/assets/index.module-Bjlhgfd1.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js:./public/vue-assets/assets/team-insights-D9P6ojjD.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-DWumv-QD.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-DiEs6xIb.js:./public/vue-assets/assets/logged-in-layout-Cq1ztH50.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kB120.67kB128.71kB129.28 kB133.44kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43kB689.63kB825.23 kB1,402.70 kB[plugin builtin:vite-reporter](!) Somechunks are larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] ₴8APP...
|
NULL
|
|
46473
|
982
|
0
|
2026-04-17T10:37:10.174302+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422230174_m2.jpg...
|
PhpStorm
|
faVsco.js – ~/jiminny/app/front-end/src/components faVsco.js – ~/jiminny/app/front-end/src/components/connect/connect.vue...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.03046875,"top":0.017361112,"width":0.0453125,"height":0.022222223},"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"bounds":{"left":0.07578125,"top":0.017361112,"width":0.15898438,"height":0.022222223},"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.78515625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"bounds":{"left":0.803125,"top":0.017361112,"width":0.09765625,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9007813,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9140625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9273437,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96015626,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9734375,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9867188,"top":0.017361112,"width":0.013281226,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.12382813,"top":0.22083333,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.13867188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"bounds":{"left":0.1515625,"top":0.22013889,"width":0.0515625,"height":0.013888889},"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.21367188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.22539063,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.23554687,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.24570313,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2/4","depth":4,"bounds":{"left":0.26171875,"top":0.21944444,"width":0.030078124,"height":0.015277778},"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.29179686,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.30195314,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.31210938,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.32226562,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2363363658988321598
|
-3089101492562299194
|
idle
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
PhpStormFileFditViewNavigateCodeLaravelRefactonToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY] Daily • in 1h 23 mA100% [z7Fri 17 Apr 13:37:09AutomatedRenortsCommandTestProject vC AutomatedReportsService.phpC) SendReportJob.phpC SendReportMailJob.phpC ReportController.phplokenbullaer.onoc leamsetuocontroller.onopnp api.pnp= custom.loc= aravel.logc SF liminny@localhostU scratch_1,jsonconnect.vue XV Onboard.vue>W testsU connect.less© Filesystem.php© Team.php© CreateHeldActivityEvent.phpC) TrackProviderInstalledEvent.phpV connect.vuedashboardC RequestGenerateReportJob.phpOpportunitySyncTrait.phpC Opportunity.phpW DeallnsightsT InteractsWithPivotTable.phgOpoorunityupdated.oneOpoorunitystadeupaated.onoD errorPagesc) FventService?rovider.onnonoortunitvPendingAiAnalvsisatterstadechanded.om_ export-portalextension-installledC RunOpportunityAiAnalysis.phpC ProcessAlAutomationAnalysiskesults.ong© ImportOpportunityBatch.phpinvitationonconterenceTImportBatchJobTrait.php(C) Service.phpWa VoUTcachedStagesX 2 Cc W .*_ LiveCoach_ Lockedtrait upportunitysynctraitA33 V2 V191154login1018private function resolverorecastcategory(?string $forecastcategory): stringi= 155_ MeetingConsent_ mobile=1562 usagesl onboardlprivate function importExternalFieldData(array $properties, int $opportunityid158•__mocks_1050159•U_tests_$crmFields = $this->getOpportunitySyncableFields:_160V MobileAppDownk1 Onboard.less1033sthis-mportopportunztycrnfzeLdbata(Spropertzes, ScrmFzelds, Sopportunty161Venhoard vilPGitLocal ChandesShelfLogConsoleLog xChanges 10 files, updatina...<→ a,Side-by-side viewerDo not ignoreaichliaht words= ,env.local aop@5bb8tefc app/Jobs/Team/SyncTolntercom.php© ActivityController.php app/Http/Controllers/APIJiminnv Joos Team > Sync Ontercom MAAAAAAMAV connect.vue front-end/src/components/connectIncercomservice sintercomservice,(© JiminnyDebugCommand.php app/Console/CommandsAculvityProv1derkeg1scry sacclvityProv1derkeg1scry.php logging.php configleamkepository +ceamkepos1tory,V Onboard.vue front-end/src/components/onboard: void {© PlaybackService.php app/Services$team = Sthis->team:© ReportController.php app/Http/Controllers/webhook// We don't want to sync partner accounts to Intercom.SyncTolntercom.php app/Jobs/Teamif (Steam->isPartnerDefault0 === false)php weo,ono routesreturn;› Unvers onee res o tles, uocarno.< Hs local liminnyalocalnost4 console [EUlC CrmEntityRepository.pho(iii) crm configurations [EU]¿ console IPROD¿ consoe STAGINGI<script>101158methods:async incegrat1onAppunclickconnection = awalt integratlonAppconsole.log('[IntegrationApp] openNewConnection rejected:', err);rerurn nucuconsole.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection)):CascadeAutomated Report RetDebugging OpportuniWodate Connectionratner than resolving with a null/disconnectea connection ob ect as it dla berore.To contirm. add a catch." isconst connection = awalt intedratlonaoointegration(this. Loca(Provider.name)onenNewconnectionshowPoweredBy: talse,allowMultipleConnections: false,}).catch((err) => 1console. loo untegrationApp openNewlonneccion relected: err;return nuuuIntegrationApp openNewConnection resolved:"id":"69e0b41a67d0068c2ca0b48e""name": "Zoho CRM""userid": "lece66c8-feb1-4df1-0521-2160/daf4623","tenantld":"69e0b3faef3e/b6248189289","Islest":ralse,"connecced": true,state ediKEALy"Accept rile ?X Reiect rle t2<3—? or? tiles →Ltiles with changesvfront-end/src/components/connect/Jconnect.vue +2 -3front-end/src/components/onboard/iOnboard.vue +1 -2View allliReject allAccept allASk anyinind dtl+ < CodeClaude Sonnet 4.6OJ164 diiterencesCurrent versionninnv Joos Team > Sync Ontercom MAAAAAAAAIntercomService $intercomService,Aculvityprov1derkeg1scry sacclvityProv1derkeg1scry,TeamRepository steamkepos1tory,): void 1$team = Sthis->team;// We don't want to sync partner accounts to Intercom1f (steam->1SPartnerDefaultO === false) 1neturn"scrm = steam->getcrmconf1guration;// Create remote Intercom company.sincercomservice->creacecompany.l"name" => pceam->gecNamel),'company_id' = $team->getUvid),'size' => $team->seats,'remote_created_at' => $team->getCreatedAt->getlimestamp,'plan' => $team->getTier()->getTitle(,'custom attributes' =>'customer_ap1' => $team->getApiToken() === null ? 'no" : 'yes",call endan'= Steam->calendar_provider,'crm' => $crm?->getProviderName) ?? '•'crm_instance' => $crm?->getAttribute('instance') ?? "',"zone" → steam->zone,'data_center' => config('jiminny.deploy_region'),'tier' => Steam->qetTierO->getTitleOlфcrm = sceam->getcrmcontigurationo:nuler = rean->ceclero.StierTitle = Stier?->aetTitleO ?? 'Unknown':1):untag allCreate remote Intercom company.sintercomService->createCompanycl'name' => $team->getNameo.'company_1d= steam->getuu1d).'size' => steam->seats,'remote_created_at = Steam->getcreatedAt->getlimestampo"plan" = pclerlitle,"custon_autributes""cuscomer_apl = steam->gecAplloken() === null : "no" : 'yes".calendar» call-ocalendar orovloer'crm' => Scrm?->qetProviderName@ ??1crn_instance=> $crm?->getAttribute('instance') ?? "','zone' => Steam->zone'data center'=> config('jiminny.deploy_region')'tier'= StierTitle1):Wsnoricuts contlicis: Clottings. #/ Modiry shortcuts // Don't show Again (today 12:22winasur leams148:28 V UTF-8[ia 2 spaces...
|
46471
|
|
46616
|
NULL
|
0
|
2026-04-17T10:42:10.835654+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422530835_m2.jpg...
|
iTerm2
|
APP (-zsh)
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
info Visit [URL_WITH_CREDENTIALS] ~/jiminny/app/fr info Visit [URL_WITH_CREDENTIALS] ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yanrn build
zsh: command not found: yanrn
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn build
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️ secrets for agents: [URL_WITH_CREDENTIALS] ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn install
➤ YN0000: · Yarn 4.12.0
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed
➤ YN0000: ┌ Post-resolution validation
➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide @testing-library/dom (pea6ced), requested by @testing-library/user-event.
➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide noty (p5bdb0d), requested by vue-components.
➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.
➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.
➤ YN0000: └ Completed
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed in 1s 655ms
➤ YN0000: ┌ Link step
➤ YN0008: │ root-workspace-0b6124@workspace:. must be rebuilt because its dependency tree changed
➤ YN0000: └ Completed in 0s 969ms
➤ YN0000: · Done with warnings in 3s 14ms
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn build
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️ override existing env vars with { override: true }
vite v8.0.0 building client environment for production...
✓ 4656 modules transformed.
[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/
[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/
computing gzip size...
../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB
../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB
../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB
../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB
../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB
../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB
../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB
../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB
../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB
../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB
../public/vue-assets/assets/[EMAIL] 66.44 kB
../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB
../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB
../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB
../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB
../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB
../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB
../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB
../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB
../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB
../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB
../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB
../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB
../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB
../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB
../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB
../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB
../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB
../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB
../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB
../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB
../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB
../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB
../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB
../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB
../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB
../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB
../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB
../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB
../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB
../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB
../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB
../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB
../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB
../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB
../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB
../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB
../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB
../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB
../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB
../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB
../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB
../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB
../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB
../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB
../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB
../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB
../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB
../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB
../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB
../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB
../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB
../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB
../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB
../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB
../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB
../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB
../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB
../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB
../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB
../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB
../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB
../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB
../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB
../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB
../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB
../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB
../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB
../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB
../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB
../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB
../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB
../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB
../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB
../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB
../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB
../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB
../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB
../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB
../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB
../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB
../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB
../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB
../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB
../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB
../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB
../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB
../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB
../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB
../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB
../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB
../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB
../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB
../public/vue-assets/assets/theme-B5VdyMN_.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB
../public/vue-assets/assets/pick-C8Pw7kHx.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB
../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB
../public/vue-assets/assets/throttle-siTOKEMt.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB
../public/vue-assets/assets/lastFilters-B_B_O5LY.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB
../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gz...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ nvm use 24\nNow using node v24.11.1 (npm v11.6.2)\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yanr build\nzsh: command not found: yanr\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yanrn build\nzsh: command not found: yanrn\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build \n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️\u0000 secrets for agents: https://dotenvx.com/as2\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.33 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-B6_hRKul.css 12.95 kB │ gzip: 2.92 kB\n../public/vue-assets/assets/tokens-CoAAv8do.css 13.41 kB │ gzip: 2.97 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-CrLnsUSQ.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-jGxSsmQW.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-DE_etUX9.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-CjyI5phg.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-DV-Svw8z.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-C6V4-Yml.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-C_yEm2e-.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-DyDQY_lm.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-DRJ7JhID.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-BrhP0P7D.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-DWZF-G8N.js 2.34 kB │ gzip: 1.23 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-CnVa_KZl.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-B2ThxTAd.js 2.59 kB │ gzip: 1.42 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-k3In5q1l.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-BZrDAfqV.js 3.45 kB │ gzip: 1.69 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-DJLlDZUr.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-DdBy-CTd.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-BYAvUsG9.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-EdnBkMBr.js 4.43 kB │ gzip: 2.04 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-B1SNfWGY.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/connect-DzHqvqqR.js 5.17 kB │ gzip: 2.28 kB │ map: 10.35 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-DbifQcp6.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-CYJkDTD8.js 6.25 kB │ gzip: 2.82 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-DkwzcZhV.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-CiBJ3oHz.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-BZWjw9pN.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-DLO6BXq1.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-prxYCVfk.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-B3i0pft-.js 15.17 kB │ gzip: 6.03 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-54ZutGpG.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-BpW-5w7g.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-Ber3EVyb.js 18.92 kB │ gzip: 6.75 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-BuNWx0BA.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-BMtylYi6.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-CP7J7-qo.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-kg1j3nIA.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-C8q7faXl.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-BgSY9SKi.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-COtjyq5c.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-bksUVN5E.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-Yn3gKP2z.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-BqxRx4zw.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-C2H2xj9g.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-BDlz4mpq.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BnVEi9yc.js 94.84 kB │ gzip: 28.16 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-CN2ZtlC7.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-XCNXJG27.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-DMzthP2u.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DYzOhe6q.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-DRpCBZO9.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-CPpPTAKV.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-Cfb59XkF.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-1Grk9P2e.js 825.23 kB │ gzip: 72.55 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-DArs1VTa.js 1,402.70 kB │ gzip: 438.08 kB │ map: 6,283.55 kB\n\n[PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:\n - vite:css (61%)\n - vite-plugin-externals (12%)\n - vite:vue (9%)\n - sentry-vite-plugin (8%)\n - vite:worker (6%)\nSee https://rolldown.rs/options/checks#plugintimings for more details.\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 22.57s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn install\n➤ YN0000: · Yarn 4.12.0\n➤ YN0000: ┌ Resolution step\n➤ YN0000: └ Completed\n➤ YN0000: ┌ Post-resolution validation\n➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide @testing-library/dom (pea6ced), requested by @testing-library/user-event.\n➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide noty (p5bdb0d), requested by vue-components.\n➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.\n➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.\n➤ YN0000: └ Completed\n➤ YN0000: ┌ Fetch step\n➤ YN0000: └ Completed in 1s 655ms\n➤ YN0000: ┌ Link step\n➤ YN0008: │ root-workspace-0b6124@workspace:. must be rebuilt because its dependency tree changed\n➤ YN0000: └ Completed in 0s 969ms\n➤ YN0000: · Done with warnings in 3s 14ms\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️\u0000 override existing env vars with { override: true }\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-B5VdyMN_.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-C8Pw7kHx.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-siTOKEMt.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-B_B_O5LY.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-CsQ1aO-4.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-7ycH7TWx.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-DUcV_uoi.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-CYQu1FG7.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-BjhdeObt.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-B2cExxmx.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings--S7_RYRE.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-cuK1068l.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-DxPLOs1S.js 2.59 kB │ gzip: 1.42 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-CVxaD0_B.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview--ydYatRe.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-CkLTUCy6.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-DPy-uEfS.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-D36CpnKB.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-C0YRJ_xR.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation--7sddGcP.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/connect-Bfq7LjjQ.js 5.17 kB │ gzip: 2.28 kB │ map: 10.35 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-Dj5DULYF.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-gY3HLgqP.js 6.25 kB │ gzip: 2.83 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-Bz_Gi9sn.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-Dgwsn6KA.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-DNS51mtN.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-CIGPrkbw.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-CPwNAOXA.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-DAEn44FQ.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-DB0CksQW.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-ClBvXCXq.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-BTQmbI4-.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-CqgLpVFE.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-4e6kQ9l_.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-CocIYUaz.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-CE8XLH98.js 26.88 kB │ gzip: 9.38 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-3DSxnTNQ.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-BQ36EoGS.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-CqCXZwrk.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-B92qaj32.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-u3UeUUz5.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-CCnYJmCP.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-CNGFZm8P.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-D6N5-ivP.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-jlkz65MZ.js 94.84 kB │ gzip: 28.16 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-DmKqYVi1.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-BWoBIPKA.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-icPKypZa.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-BZ-J0giH.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-DKsqp_aL.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-D9P6ojjD.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-DWumv-QD.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-DiEs6xIb.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-Cq1ztH5O.js 1,402.70 kB │ gzip: 438.08 kB │ map: 6,283.55 kB\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 13.59s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️\u0000 load multiple .env files with { path: ['.env.local', '.env'] }\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.33 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-CrWye7yo.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-D-kTQpNV.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-CEV1oVAM.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-D3xNTqAt.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-DftTc1_7.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-CK0K0ozg.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-DLwqdmK8.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-D8zd6tGl.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-D8AEMpQD.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-DZPkx2YQ.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-DHjh0S4O.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-CTc8r0pe.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-CHodD5F8.js 2.59 kB │ gzip: 1.43 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-CS9P7JeF.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-Dkxw0lkq.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-BdRuUFYY.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-Cploop1A.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-Cz-Y-wOJ.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-DZKBS9eW.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-DUWFWQvr.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/connect-LR_dB_VC.js 5.25 kB │ gzip: 2.30 kB │ map: 10.52 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-C6KkT8e1.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-D5dWNU9i.js 6.25 kB │ gzip: 2.82 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-DGWP8lD_.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-zafDvh_H.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-Co9u0t34.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-C820ZfzV.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-CfDB_Ohb.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-BhbjZb-1.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-BM3w9d6h.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-Kj7lCx0-.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-ulzm9gk2.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-C9INej-u.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-C-6FGhqy.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-mZhlfeUe.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-mq9zQOVK.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-BUgW-21G.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-CVCNDjsB.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-Cu4TbCsZ.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-CoZZkbGt.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-BpFWtNz1.js 48.28 kB │ gzip: 15.08 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-D27tiAEp.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-Dmn6sJ5_.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-DO4wa1Ld.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BKxR7Ag9.js 94.84 kB │ gzip: 28.17 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-V1cngeeb.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-D0nLYfJh.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-zRF85Jni.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DXmpAhyV.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-BerPTevk.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-Rfo09TvE.js 298.57 kB │ gzip: 77.21 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-BkQge7FT.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-RakUX3TF.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-WZXlxzkM.js 1,402.70 kB │ gzip: 438.07 kB │ map: 6,283.55 kB\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 25.43s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️\u0000 secrets for agents: https://dotenvx.com/as2\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-Cy-WIInU.js 0.63 kB │ gzip: 0.42 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-BGRRe-Qj.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-DmtOZ8h1.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-CzSBGyMt.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-BtwCuAYd.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-DG3xxJjJ.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-mV_4t574.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-g60shJd4.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-Z27Z5klt.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-Cn_qGwMd.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-BSSIkavG.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-C5_UlocO.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-Bad3U1k5.js 2.59 kB │ gzip: 1.43 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-D11UHzKP.js 2.97 kB │ gzip: 1.51 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-CoaCdIkx.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-C452yEnj.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-CloJVGCY.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-DJ4M3rJ1.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-B24mqvl1.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-B5F0aLwl.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/connect-DvCp38Q2.js 5.31 kB │ gzip: 2.31 kB │ map: 10.62 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-BvWVN0nz.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-CLdXMCwD.js 6.25 kB │ gzip: 2.83 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-PrWVOMsr.js 7.02 kB │ gzip: 3.17 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-BH9WFuby.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-DmPJHAz_.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-CQou30yT.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-BS8w3ovp.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-Cy_xmRg8.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-CZ2b-FlS.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-CdvjTszI.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-B1v5HdqS.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-uKCSfiLo.js 21.92 kB │ gzip: 8.55 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-zCtNIOGN.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-D5_z7YdA.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-mxFxJiHI.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-D7gUVql5.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-DgI0NfRA.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-BqQiLGFF.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-D4YlPwr_.js 43.22 kB │ gzip: 14.35 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-BWAdERcJ.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-CyAPGoFk.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-DNHiCr2i.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-dfcpodo5.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BVnPilVP.js 94.84 kB │ gzip: 28.17 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-DJD6SV4A.js 115.71 kB │ gzip: 33.79 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-CsDOiLAi.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-B3B1ZM6O.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DatDldIe.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-D1gm80qQ.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-DRugjYCA.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-CxSmZv7h.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-Cp0YOK4U.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-CE9ox17M.js 1,402.70 kB │ gzip: 438.07 kB │ map: 6,283.55 kB\n\n✓ built in 26.01s\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $","depth":4,"value":"info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ nvm use 24\nNow using node v24.11.1 (npm v11.6.2)\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yanr build\nzsh: command not found: yanr\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yanrn build\nzsh: command not found: yanrn\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build \n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️\u0000 secrets for agents: https://dotenvx.com/as2\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.33 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-B6_hRKul.css 12.95 kB │ gzip: 2.92 kB\n../public/vue-assets/assets/tokens-CoAAv8do.css 13.41 kB │ gzip: 2.97 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-CrLnsUSQ.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-jGxSsmQW.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-DE_etUX9.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-CjyI5phg.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-DV-Svw8z.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-C6V4-Yml.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-C_yEm2e-.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-DyDQY_lm.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-DRJ7JhID.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-BrhP0P7D.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-DWZF-G8N.js 2.34 kB │ gzip: 1.23 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-CnVa_KZl.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-B2ThxTAd.js 2.59 kB │ gzip: 1.42 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-k3In5q1l.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-BZrDAfqV.js 3.45 kB │ gzip: 1.69 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-DJLlDZUr.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-DdBy-CTd.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-BYAvUsG9.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-EdnBkMBr.js 4.43 kB │ gzip: 2.04 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-B1SNfWGY.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/connect-DzHqvqqR.js 5.17 kB │ gzip: 2.28 kB │ map: 10.35 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-DbifQcp6.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-CYJkDTD8.js 6.25 kB │ gzip: 2.82 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-DkwzcZhV.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-CiBJ3oHz.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-BZWjw9pN.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-DLO6BXq1.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-prxYCVfk.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-B3i0pft-.js 15.17 kB │ gzip: 6.03 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-54ZutGpG.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-BpW-5w7g.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-Ber3EVyb.js 18.92 kB │ gzip: 6.75 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-BuNWx0BA.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-BMtylYi6.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-CP7J7-qo.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-kg1j3nIA.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-C8q7faXl.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-BgSY9SKi.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-COtjyq5c.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-bksUVN5E.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-Yn3gKP2z.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-BqxRx4zw.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-C2H2xj9g.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-BDlz4mpq.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BnVEi9yc.js 94.84 kB │ gzip: 28.16 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-CN2ZtlC7.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-XCNXJG27.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-DMzthP2u.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DYzOhe6q.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-DRpCBZO9.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-CPpPTAKV.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-Cfb59XkF.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-1Grk9P2e.js 825.23 kB │ gzip: 72.55 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-DArs1VTa.js 1,402.70 kB │ gzip: 438.08 kB │ map: 6,283.55 kB\n\n[PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:\n - vite:css (61%)\n - vite-plugin-externals (12%)\n - vite:vue (9%)\n - sentry-vite-plugin (8%)\n - vite:worker (6%)\nSee https://rolldown.rs/options/checks#plugintimings for more details.\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 22.57s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn install\n➤ YN0000: · Yarn 4.12.0\n➤ YN0000: ┌ Resolution step\n➤ YN0000: └ Completed\n➤ YN0000: ┌ Post-resolution validation\n➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide @testing-library/dom (pea6ced), requested by @testing-library/user-event.\n➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide noty (p5bdb0d), requested by vue-components.\n➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.\n➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.\n➤ YN0000: └ Completed\n➤ YN0000: ┌ Fetch step\n➤ YN0000: └ Completed in 1s 655ms\n➤ YN0000: ┌ Link step\n➤ YN0008: │ root-workspace-0b6124@workspace:. must be rebuilt because its dependency tree changed\n➤ YN0000: └ Completed in 0s 969ms\n➤ YN0000: · Done with warnings in 3s 14ms\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️\u0000 override existing env vars with { override: true }\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-B5VdyMN_.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-C8Pw7kHx.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-siTOKEMt.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-B_B_O5LY.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-CsQ1aO-4.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-7ycH7TWx.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-DUcV_uoi.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-CYQu1FG7.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-BjhdeObt.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-B2cExxmx.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings--S7_RYRE.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-cuK1068l.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-DxPLOs1S.js 2.59 kB │ gzip: 1.42 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-CVxaD0_B.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview--ydYatRe.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-CkLTUCy6.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-DPy-uEfS.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-D36CpnKB.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-C0YRJ_xR.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation--7sddGcP.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/connect-Bfq7LjjQ.js 5.17 kB │ gzip: 2.28 kB │ map: 10.35 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-Dj5DULYF.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-gY3HLgqP.js 6.25 kB │ gzip: 2.83 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-Bz_Gi9sn.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-Dgwsn6KA.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-DNS51mtN.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-CIGPrkbw.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-CPwNAOXA.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-DAEn44FQ.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-DB0CksQW.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-ClBvXCXq.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-BTQmbI4-.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-CqgLpVFE.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-4e6kQ9l_.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-CocIYUaz.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-CE8XLH98.js 26.88 kB │ gzip: 9.38 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-3DSxnTNQ.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-BQ36EoGS.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-CqCXZwrk.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-B92qaj32.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-u3UeUUz5.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-CCnYJmCP.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-CNGFZm8P.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-D6N5-ivP.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-jlkz65MZ.js 94.84 kB │ gzip: 28.16 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-DmKqYVi1.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-BWoBIPKA.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-icPKypZa.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-BZ-J0giH.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-DKsqp_aL.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-D9P6ojjD.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-DWumv-QD.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-DiEs6xIb.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-Cq1ztH5O.js 1,402.70 kB │ gzip: 438.08 kB │ map: 6,283.55 kB\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 13.59s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️\u0000 load multiple .env files with { path: ['.env.local', '.env'] }\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.33 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-CrWye7yo.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-D-kTQpNV.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-CEV1oVAM.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-D3xNTqAt.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-DftTc1_7.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-CK0K0ozg.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-DLwqdmK8.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-D8zd6tGl.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-D8AEMpQD.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-DZPkx2YQ.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-DHjh0S4O.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-CTc8r0pe.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-CHodD5F8.js 2.59 kB │ gzip: 1.43 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-CS9P7JeF.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-Dkxw0lkq.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-BdRuUFYY.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-Cploop1A.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-Cz-Y-wOJ.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-DZKBS9eW.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-DUWFWQvr.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/connect-LR_dB_VC.js 5.25 kB │ gzip: 2.30 kB │ map: 10.52 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-C6KkT8e1.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-D5dWNU9i.js 6.25 kB │ gzip: 2.82 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-DGWP8lD_.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-zafDvh_H.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-Co9u0t34.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-C820ZfzV.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-CfDB_Ohb.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-BhbjZb-1.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-BM3w9d6h.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-Kj7lCx0-.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-ulzm9gk2.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-C9INej-u.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-C-6FGhqy.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-mZhlfeUe.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-mq9zQOVK.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-BUgW-21G.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-CVCNDjsB.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-Cu4TbCsZ.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-CoZZkbGt.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-BpFWtNz1.js 48.28 kB │ gzip: 15.08 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-D27tiAEp.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-Dmn6sJ5_.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-DO4wa1Ld.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BKxR7Ag9.js 94.84 kB │ gzip: 28.17 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-V1cngeeb.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-D0nLYfJh.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-zRF85Jni.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DXmpAhyV.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-BerPTevk.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-Rfo09TvE.js 298.57 kB │ gzip: 77.21 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-BkQge7FT.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-RakUX3TF.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-WZXlxzkM.js 1,402.70 kB │ gzip: 438.07 kB │ map: 6,283.55 kB\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 25.43s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️\u0000 secrets for agents: https://dotenvx.com/as2\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-Cy-WIInU.js 0.63 kB │ gzip: 0.42 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-BGRRe-Qj.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-DmtOZ8h1.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-CzSBGyMt.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-BtwCuAYd.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-DG3xxJjJ.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-mV_4t574.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-g60shJd4.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-Z27Z5klt.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-Cn_qGwMd.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-BSSIkavG.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-C5_UlocO.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-Bad3U1k5.js 2.59 kB │ gzip: 1.43 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-D11UHzKP.js 2.97 kB │ gzip: 1.51 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-CoaCdIkx.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-C452yEnj.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-CloJVGCY.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-DJ4M3rJ1.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-B24mqvl1.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-B5F0aLwl.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/connect-DvCp38Q2.js 5.31 kB │ gzip: 2.31 kB │ map: 10.62 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-BvWVN0nz.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-CLdXMCwD.js 6.25 kB │ gzip: 2.83 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-PrWVOMsr.js 7.02 kB │ gzip: 3.17 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-BH9WFuby.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-DmPJHAz_.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-CQou30yT.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-BS8w3ovp.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-Cy_xmRg8.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-CZ2b-FlS.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-CdvjTszI.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-B1v5HdqS.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-uKCSfiLo.js 21.92 kB │ gzip: 8.55 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-zCtNIOGN.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-D5_z7YdA.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-mxFxJiHI.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-D7gUVql5.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-DgI0NfRA.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-BqQiLGFF.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-D4YlPwr_.js 43.22 kB │ gzip: 14.35 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-BWAdERcJ.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-CyAPGoFk.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-DNHiCr2i.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-dfcpodo5.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BVnPilVP.js 94.84 kB │ gzip: 28.17 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-DJD6SV4A.js 115.71 kB │ gzip: 33.79 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-CsDOiLAi.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-B3B1ZM6O.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DatDldIe.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-D1gm80qQ.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-DRugjYCA.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-CxSmZv7h.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-Cp0YOK4U.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-CE9ox17M.js 1,402.70 kB │ gzip: 438.07 kB │ map: 6,283.55 kB\n\n✓ built in 26.01s\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.23359375,"top":1.0,"width":0.06914063,"height":-0.037500024},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.2359375,"top":1.0,"width":0.00625,"height":-0.04027772},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.30273438,"top":1.0,"width":0.06914063,"height":-0.037500024},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.30507812,"top":1.0,"width":0.00625,"height":-0.04027772},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.371875,"top":1.0,"width":0.06914063,"height":-0.037500024},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.37421876,"top":1.0,"width":0.00625,"height":-0.04027772},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.44101563,"top":1.0,"width":0.06914063,"height":-0.037500024},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.44335938,"top":1.0,"width":0.00625,"height":-0.04027772},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.5101563,"top":1.0,"width":0.06914063,"height":-0.037500024},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.5125,"top":1.0,"width":0.00625,"height":-0.04027772},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"✳ Review screenpipe usage and Boosteroid integration (claude)","depth":2,"bounds":{"left":0.5792969,"top":1.0,"width":0.06914063,"height":-0.037500024},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.5816406,"top":1.0,"width":0.00625,"height":-0.04027772},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"ec2-user@ip-10-30-159-186:~ (nc)","depth":2,"bounds":{"left":0.6484375,"top":1.0,"width":0.06914063,"height":-0.037500024},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.6507813,"top":1.0,"width":0.00625,"height":-0.04027772},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"ec2-user@ip-10-20-6-111:~ (nc)","depth":2,"bounds":{"left":0.7175781,"top":1.0,"width":0.06914063,"height":-0.037500024},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.7199219,"top":1.0,"width":0.00625,"height":-0.04027772},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.77070314,"top":1.0,"width":0.021875,"height":-0.020833373},"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"APP (-zsh)","depth":1,"bounds":{"left":0.50039065,"top":1.0,"width":0.02890625,"height":-0.021527767},"role_description":"text"}]...
|
-2407191479157132203
|
3429803486563842285
|
idle
|
accessibility
|
NULL
|
info Visit [URL_WITH_CREDENTIALS] ~/jiminny/app/fr info Visit [URL_WITH_CREDENTIALS] ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yanrn build
zsh: command not found: yanrn
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn build
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️ secrets for agents: [URL_WITH_CREDENTIALS] ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn install
➤ YN0000: · Yarn 4.12.0
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed
➤ YN0000: ┌ Post-resolution validation
➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide @testing-library/dom (pea6ced), requested by @testing-library/user-event.
➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide noty (p5bdb0d), requested by vue-components.
➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.
➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.
➤ YN0000: └ Completed
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed in 1s 655ms
➤ YN0000: ┌ Link step
➤ YN0008: │ root-workspace-0b6124@workspace:. must be rebuilt because its dependency tree changed
➤ YN0000: └ Completed in 0s 969ms
➤ YN0000: · Done with warnings in 3s 14ms
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn build
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️ override existing env vars with { override: true }
vite v8.0.0 building client environment for production...
✓ 4656 modules transformed.
[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/
[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/
computing gzip size...
../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB
../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB
../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB
../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB
../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB
../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB
../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB
../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB
../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB
../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB
../public/vue-assets/assets/[EMAIL] 66.44 kB
../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB
../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB
../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB
../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB
../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB
../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB
../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB
../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB
../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB
../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB
../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB
../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB
../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB
../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB
../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB
../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB
../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB
../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB
../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB
../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB
../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB
../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB
../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB
../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB
../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB
../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB
../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB
../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB
../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB
../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB
../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB
../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB
../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB
../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB
../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB
../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB
../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB
../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB
../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB
../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB
../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB
../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB
../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB
../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB
../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB
../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB
../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB
../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB
../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB
../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB
../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB
../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB
../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB
../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB
../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB
../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB
../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB
../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB
../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB
../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB
../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB
../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB
../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB
../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB
../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB
../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB
../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB
../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB
../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB
../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB
../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB
../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB
../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB
../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB
../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB
../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB
../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB
../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB
../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB
../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB
../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB
../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB
../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB
../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB
../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB
../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB
../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB
../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB
../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB
../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB
../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB
../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB
../public/vue-assets/assets/theme-B5VdyMN_.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB
../public/vue-assets/assets/pick-C8Pw7kHx.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB
../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB
../public/vue-assets/assets/throttle-siTOKEMt.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB
../public/vue-assets/assets/lastFilters-B_B_O5LY.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB
../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gz...
|
NULL
|
|
46617
|
NULL
|
0
|
2026-04-17T10:42:18.997032+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422538997_m1.jpg...
|
iTerm2
|
APP (-zsh)
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
info Visit [URL_WITH_CREDENTIALS] ~/jiminny/app/fr info Visit [URL_WITH_CREDENTIALS] ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yanrn build
zsh: command not found: yanrn
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn build
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️ secrets for agents: [URL_WITH_CREDENTIALS] ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn install
➤ YN0000: · Yarn 4.12.0
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed
➤ YN0000: ┌ Post-resolution validation
➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide @testing-library/dom (pea6ced), requested by @testing-library/user-event.
➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide noty (p5bdb0d), requested by vue-components.
➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.
➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.
➤ YN0000: └ Completed
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed in 1s 655ms
➤ YN0000: ┌ Link step
➤ YN0008: │ root-workspace-0b6124@workspace:. must be rebuilt because its dependency tree changed
➤ YN0000: └ Completed in 0s 969ms
➤ YN0000: · Done with warnings in 3s 14ms
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn build
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️ override existing env vars with { override: true }
vite v8.0.0 building client environment for production...
✓ 4656 modules transformed.
[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/
[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/
computing gzip size...
../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB
../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB
../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB
../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB
../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB
../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB
../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB
../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB
../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB
../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB
../public/vue-assets/assets/[EMAIL] 66.44 kB
../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB
../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB
../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB
../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB
../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB
../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB
../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB
../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB
../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB
../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB
../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB
../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB
../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB
../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB
../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB
../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB
../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB
../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB
../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB
../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB
../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB
../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB
../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB
../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB
../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB
../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB
../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB
../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB
../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB
../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB
../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB
../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB
../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB
../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB
../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB
../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB
../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB
../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB
../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB
../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB
../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB
../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB
../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB
../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB
../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB
../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB
../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB
../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB
../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB
../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB
../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB
../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB
../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB
../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB
../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB
../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB
../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB
../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB
../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB
../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB
../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB
../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB
../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB
../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB
../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB
../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB
../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB
../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB
../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB
../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB
../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB
../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB
../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB
../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB
../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB
../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB
../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB
../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB
../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB
../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB
../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB
../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB
../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB
../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB
../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB
../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB
../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB
../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB
../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB
../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB
../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB
../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB
../public/vue-assets/assets/theme-B5VdyMN_.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB
../public/vue-assets/assets/pick-C8Pw7kHx.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB
../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB
../public/vue-assets/assets/throttle-siTOKEMt.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB
../public/vue-assets/assets/lastFilters-B_B_O5LY.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB
../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gz...
|
[{"role":"AXTextArea","text [{"role":"AXTextArea","text":"info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ nvm use 24\nNow using node v24.11.1 (npm v11.6.2)\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yanr build\nzsh: command not found: yanr\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yanrn build\nzsh: command not found: yanrn\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build \n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️\u0000 secrets for agents: https://dotenvx.com/as2\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.33 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-B6_hRKul.css 12.95 kB │ gzip: 2.92 kB\n../public/vue-assets/assets/tokens-CoAAv8do.css 13.41 kB │ gzip: 2.97 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-CrLnsUSQ.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-jGxSsmQW.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-DE_etUX9.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-CjyI5phg.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-DV-Svw8z.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-C6V4-Yml.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-C_yEm2e-.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-DyDQY_lm.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-DRJ7JhID.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-BrhP0P7D.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-DWZF-G8N.js 2.34 kB │ gzip: 1.23 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-CnVa_KZl.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-B2ThxTAd.js 2.59 kB │ gzip: 1.42 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-k3In5q1l.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-BZrDAfqV.js 3.45 kB │ gzip: 1.69 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-DJLlDZUr.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-DdBy-CTd.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-BYAvUsG9.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-EdnBkMBr.js 4.43 kB │ gzip: 2.04 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-B1SNfWGY.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/connect-DzHqvqqR.js 5.17 kB │ gzip: 2.28 kB │ map: 10.35 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-DbifQcp6.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-CYJkDTD8.js 6.25 kB │ gzip: 2.82 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-DkwzcZhV.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-CiBJ3oHz.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-BZWjw9pN.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-DLO6BXq1.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-prxYCVfk.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-B3i0pft-.js 15.17 kB │ gzip: 6.03 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-54ZutGpG.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-BpW-5w7g.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-Ber3EVyb.js 18.92 kB │ gzip: 6.75 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-BuNWx0BA.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-BMtylYi6.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-CP7J7-qo.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-kg1j3nIA.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-C8q7faXl.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-BgSY9SKi.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-COtjyq5c.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-bksUVN5E.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-Yn3gKP2z.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-BqxRx4zw.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-C2H2xj9g.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-BDlz4mpq.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BnVEi9yc.js 94.84 kB │ gzip: 28.16 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-CN2ZtlC7.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-XCNXJG27.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-DMzthP2u.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DYzOhe6q.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-DRpCBZO9.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-CPpPTAKV.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-Cfb59XkF.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-1Grk9P2e.js 825.23 kB │ gzip: 72.55 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-DArs1VTa.js 1,402.70 kB │ gzip: 438.08 kB │ map: 6,283.55 kB\n\n[PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:\n - vite:css (61%)\n - vite-plugin-externals (12%)\n - vite:vue (9%)\n - sentry-vite-plugin (8%)\n - vite:worker (6%)\nSee https://rolldown.rs/options/checks#plugintimings for more details.\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 22.57s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn install\n➤ YN0000: · Yarn 4.12.0\n➤ YN0000: ┌ Resolution step\n➤ YN0000: └ Completed\n➤ YN0000: ┌ Post-resolution validation\n➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide @testing-library/dom (pea6ced), requested by @testing-library/user-event.\n➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide noty (p5bdb0d), requested by vue-components.\n➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.\n➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.\n➤ YN0000: └ Completed\n➤ YN0000: ┌ Fetch step\n➤ YN0000: └ Completed in 1s 655ms\n➤ YN0000: ┌ Link step\n➤ YN0008: │ root-workspace-0b6124@workspace:. must be rebuilt because its dependency tree changed\n➤ YN0000: └ Completed in 0s 969ms\n➤ YN0000: · Done with warnings in 3s 14ms\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️\u0000 override existing env vars with { override: true }\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-B5VdyMN_.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-C8Pw7kHx.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-siTOKEMt.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-B_B_O5LY.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-CsQ1aO-4.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-7ycH7TWx.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-DUcV_uoi.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-CYQu1FG7.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-BjhdeObt.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-B2cExxmx.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings--S7_RYRE.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-cuK1068l.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-DxPLOs1S.js 2.59 kB │ gzip: 1.42 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-CVxaD0_B.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview--ydYatRe.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-CkLTUCy6.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-DPy-uEfS.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-D36CpnKB.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-C0YRJ_xR.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation--7sddGcP.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/connect-Bfq7LjjQ.js 5.17 kB │ gzip: 2.28 kB │ map: 10.35 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-Dj5DULYF.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-gY3HLgqP.js 6.25 kB │ gzip: 2.83 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-Bz_Gi9sn.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-Dgwsn6KA.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-DNS51mtN.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-CIGPrkbw.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-CPwNAOXA.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-DAEn44FQ.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-DB0CksQW.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-ClBvXCXq.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-BTQmbI4-.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-CqgLpVFE.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-4e6kQ9l_.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-CocIYUaz.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-CE8XLH98.js 26.88 kB │ gzip: 9.38 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-3DSxnTNQ.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-BQ36EoGS.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-CqCXZwrk.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-B92qaj32.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-u3UeUUz5.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-CCnYJmCP.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-CNGFZm8P.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-D6N5-ivP.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-jlkz65MZ.js 94.84 kB │ gzip: 28.16 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-DmKqYVi1.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-BWoBIPKA.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-icPKypZa.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-BZ-J0giH.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-DKsqp_aL.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-D9P6ojjD.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-DWumv-QD.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-DiEs6xIb.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-Cq1ztH5O.js 1,402.70 kB │ gzip: 438.08 kB │ map: 6,283.55 kB\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 13.59s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️\u0000 load multiple .env files with { path: ['.env.local', '.env'] }\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.33 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-CrWye7yo.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-D-kTQpNV.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-CEV1oVAM.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-D3xNTqAt.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-DftTc1_7.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-CK0K0ozg.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-DLwqdmK8.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-D8zd6tGl.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-D8AEMpQD.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-DZPkx2YQ.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-DHjh0S4O.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-CTc8r0pe.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-CHodD5F8.js 2.59 kB │ gzip: 1.43 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-CS9P7JeF.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-Dkxw0lkq.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-BdRuUFYY.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-Cploop1A.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-Cz-Y-wOJ.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-DZKBS9eW.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-DUWFWQvr.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/connect-LR_dB_VC.js 5.25 kB │ gzip: 2.30 kB │ map: 10.52 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-C6KkT8e1.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-D5dWNU9i.js 6.25 kB │ gzip: 2.82 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-DGWP8lD_.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-zafDvh_H.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-Co9u0t34.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-C820ZfzV.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-CfDB_Ohb.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-BhbjZb-1.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-BM3w9d6h.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-Kj7lCx0-.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-ulzm9gk2.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-C9INej-u.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-C-6FGhqy.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-mZhlfeUe.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-mq9zQOVK.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-BUgW-21G.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-CVCNDjsB.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-Cu4TbCsZ.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-CoZZkbGt.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-BpFWtNz1.js 48.28 kB │ gzip: 15.08 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-D27tiAEp.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-Dmn6sJ5_.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-DO4wa1Ld.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BKxR7Ag9.js 94.84 kB │ gzip: 28.17 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-V1cngeeb.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-D0nLYfJh.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-zRF85Jni.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DXmpAhyV.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-BerPTevk.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-Rfo09TvE.js 298.57 kB │ gzip: 77.21 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-BkQge7FT.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-RakUX3TF.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-WZXlxzkM.js 1,402.70 kB │ gzip: 438.07 kB │ map: 6,283.55 kB\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 25.43s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️\u0000 secrets for agents: https://dotenvx.com/as2\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-Cy-WIInU.js 0.63 kB │ gzip: 0.42 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-BGRRe-Qj.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-DmtOZ8h1.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-CzSBGyMt.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-BtwCuAYd.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-DG3xxJjJ.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-mV_4t574.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-g60shJd4.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-Z27Z5klt.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-Cn_qGwMd.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-BSSIkavG.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-C5_UlocO.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-Bad3U1k5.js 2.59 kB │ gzip: 1.43 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-D11UHzKP.js 2.97 kB │ gzip: 1.51 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-CoaCdIkx.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-C452yEnj.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-CloJVGCY.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-DJ4M3rJ1.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-B24mqvl1.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-B5F0aLwl.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/connect-DvCp38Q2.js 5.31 kB │ gzip: 2.31 kB │ map: 10.62 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-BvWVN0nz.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-CLdXMCwD.js 6.25 kB │ gzip: 2.83 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-PrWVOMsr.js 7.02 kB │ gzip: 3.17 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-BH9WFuby.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-DmPJHAz_.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-CQou30yT.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-BS8w3ovp.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-Cy_xmRg8.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-CZ2b-FlS.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-CdvjTszI.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-B1v5HdqS.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-uKCSfiLo.js 21.92 kB │ gzip: 8.55 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-zCtNIOGN.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-D5_z7YdA.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-mxFxJiHI.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-D7gUVql5.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-DgI0NfRA.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-BqQiLGFF.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-D4YlPwr_.js 43.22 kB │ gzip: 14.35 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-BWAdERcJ.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-CyAPGoFk.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-DNHiCr2i.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-dfcpodo5.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BVnPilVP.js 94.84 kB │ gzip: 28.17 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-DJD6SV4A.js 115.71 kB │ gzip: 33.79 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-CsDOiLAi.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-B3B1ZM6O.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DatDldIe.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-D1gm80qQ.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-DRugjYCA.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-CxSmZv7h.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-Cp0YOK4U.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-CE9ox17M.js 1,402.70 kB │ gzip: 438.07 kB │ map: 6,283.55 kB\n\n✓ built in 26.01s\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $","depth":4,"value":"info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ nvm use 24\nNow using node v24.11.1 (npm v11.6.2)\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yanr build\nzsh: command not found: yanr\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yanrn build\nzsh: command not found: yanrn\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build \n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️\u0000 secrets for agents: https://dotenvx.com/as2\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.33 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-B6_hRKul.css 12.95 kB │ gzip: 2.92 kB\n../public/vue-assets/assets/tokens-CoAAv8do.css 13.41 kB │ gzip: 2.97 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-CrLnsUSQ.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-jGxSsmQW.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-DE_etUX9.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-CjyI5phg.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-DV-Svw8z.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-C6V4-Yml.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-C_yEm2e-.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-DyDQY_lm.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-DRJ7JhID.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-BrhP0P7D.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-DWZF-G8N.js 2.34 kB │ gzip: 1.23 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-CnVa_KZl.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-B2ThxTAd.js 2.59 kB │ gzip: 1.42 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-k3In5q1l.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-BZrDAfqV.js 3.45 kB │ gzip: 1.69 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-DJLlDZUr.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-DdBy-CTd.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-BYAvUsG9.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-EdnBkMBr.js 4.43 kB │ gzip: 2.04 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-B1SNfWGY.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/connect-DzHqvqqR.js 5.17 kB │ gzip: 2.28 kB │ map: 10.35 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-DbifQcp6.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-CYJkDTD8.js 6.25 kB │ gzip: 2.82 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-DkwzcZhV.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-CiBJ3oHz.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-BZWjw9pN.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-DLO6BXq1.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-prxYCVfk.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-B3i0pft-.js 15.17 kB │ gzip: 6.03 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-54ZutGpG.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-BpW-5w7g.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-Ber3EVyb.js 18.92 kB │ gzip: 6.75 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-BuNWx0BA.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-BMtylYi6.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-CP7J7-qo.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-kg1j3nIA.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-C8q7faXl.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-BgSY9SKi.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-COtjyq5c.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-bksUVN5E.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-Yn3gKP2z.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-BqxRx4zw.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-C2H2xj9g.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-BDlz4mpq.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BnVEi9yc.js 94.84 kB │ gzip: 28.16 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-CN2ZtlC7.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-XCNXJG27.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-DMzthP2u.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DYzOhe6q.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-DRpCBZO9.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-CPpPTAKV.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-Cfb59XkF.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-1Grk9P2e.js 825.23 kB │ gzip: 72.55 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-DArs1VTa.js 1,402.70 kB │ gzip: 438.08 kB │ map: 6,283.55 kB\n\n[PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:\n - vite:css (61%)\n - vite-plugin-externals (12%)\n - vite:vue (9%)\n - sentry-vite-plugin (8%)\n - vite:worker (6%)\nSee https://rolldown.rs/options/checks#plugintimings for more details.\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 22.57s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn install\n➤ YN0000: · Yarn 4.12.0\n➤ YN0000: ┌ Resolution step\n➤ YN0000: └ Completed\n➤ YN0000: ┌ Post-resolution validation\n➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide @testing-library/dom (pea6ced), requested by @testing-library/user-event.\n➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide noty (p5bdb0d), requested by vue-components.\n➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.\n➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.\n➤ YN0000: └ Completed\n➤ YN0000: ┌ Fetch step\n➤ YN0000: └ Completed in 1s 655ms\n➤ YN0000: ┌ Link step\n➤ YN0008: │ root-workspace-0b6124@workspace:. must be rebuilt because its dependency tree changed\n➤ YN0000: └ Completed in 0s 969ms\n➤ YN0000: · Done with warnings in 3s 14ms\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️\u0000 override existing env vars with { override: true }\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-B5VdyMN_.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-C8Pw7kHx.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-siTOKEMt.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-B_B_O5LY.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-CsQ1aO-4.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-7ycH7TWx.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-DUcV_uoi.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-CYQu1FG7.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-BjhdeObt.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-B2cExxmx.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings--S7_RYRE.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-cuK1068l.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-DxPLOs1S.js 2.59 kB │ gzip: 1.42 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-CVxaD0_B.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview--ydYatRe.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-CkLTUCy6.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-DPy-uEfS.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-D36CpnKB.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-C0YRJ_xR.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation--7sddGcP.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/connect-Bfq7LjjQ.js 5.17 kB │ gzip: 2.28 kB │ map: 10.35 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-Dj5DULYF.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-gY3HLgqP.js 6.25 kB │ gzip: 2.83 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-Bz_Gi9sn.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-Dgwsn6KA.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-DNS51mtN.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-CIGPrkbw.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-CPwNAOXA.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-DAEn44FQ.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-DB0CksQW.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-ClBvXCXq.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-BTQmbI4-.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-CqgLpVFE.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-4e6kQ9l_.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-CocIYUaz.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-CE8XLH98.js 26.88 kB │ gzip: 9.38 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-3DSxnTNQ.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-BQ36EoGS.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-CqCXZwrk.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-B92qaj32.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-u3UeUUz5.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-CCnYJmCP.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-CNGFZm8P.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-D6N5-ivP.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-jlkz65MZ.js 94.84 kB │ gzip: 28.16 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-DmKqYVi1.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-BWoBIPKA.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-icPKypZa.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-BZ-J0giH.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-DKsqp_aL.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-D9P6ojjD.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-DWumv-QD.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-DiEs6xIb.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-Cq1ztH5O.js 1,402.70 kB │ gzip: 438.08 kB │ map: 6,283.55 kB\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 13.59s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️\u0000 load multiple .env files with { path: ['.env.local', '.env'] }\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.33 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-CrWye7yo.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-D-kTQpNV.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-CEV1oVAM.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-D3xNTqAt.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-DftTc1_7.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-CK0K0ozg.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-DLwqdmK8.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-D8zd6tGl.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-D8AEMpQD.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-DZPkx2YQ.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-DHjh0S4O.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-CTc8r0pe.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-CHodD5F8.js 2.59 kB │ gzip: 1.43 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-CS9P7JeF.js 2.97 kB │ gzip: 1.50 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-Dkxw0lkq.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-BdRuUFYY.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-Cploop1A.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-Cz-Y-wOJ.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-DZKBS9eW.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-DUWFWQvr.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/connect-LR_dB_VC.js 5.25 kB │ gzip: 2.30 kB │ map: 10.52 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-C6KkT8e1.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-D5dWNU9i.js 6.25 kB │ gzip: 2.82 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-DGWP8lD_.js 7.02 kB │ gzip: 3.16 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-zafDvh_H.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-Co9u0t34.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-C820ZfzV.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-CfDB_Ohb.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-BhbjZb-1.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-BM3w9d6h.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-Kj7lCx0-.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-ulzm9gk2.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-C9INej-u.js 21.92 kB │ gzip: 8.54 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-C-6FGhqy.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-mZhlfeUe.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-mq9zQOVK.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-BUgW-21G.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-CVCNDjsB.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-Cu4TbCsZ.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-CoZZkbGt.js 43.22 kB │ gzip: 14.34 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-BpFWtNz1.js 48.28 kB │ gzip: 15.08 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-D27tiAEp.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-Dmn6sJ5_.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-DO4wa1Ld.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BKxR7Ag9.js 94.84 kB │ gzip: 28.17 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-V1cngeeb.js 115.71 kB │ gzip: 33.78 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-D0nLYfJh.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-zRF85Jni.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DXmpAhyV.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-BerPTevk.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-Rfo09TvE.js 298.57 kB │ gzip: 77.21 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-BkQge7FT.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-RakUX3TF.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-WZXlxzkM.js 1,402.70 kB │ gzip: 438.07 kB │ map: 6,283.55 kB\n\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\n✓ built in 25.43s\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $ yarn build\n[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️\u0000 secrets for agents: https://dotenvx.com/as2\nvite v8.0.0 building client environment for production...\n✓ 4656 modules transformed.\n[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\n[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/\ncomputing gzip size...\n../public/vue-assets/index.html 4.58 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB\n../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB\n../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB\n../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB\n../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB\n../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB\n../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB\n../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB\n../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB\n../public/vue-assets/assets/flags@2x-gR6KPp3x.webp 66.44 kB\n../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB\n../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB\n../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB\n../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB\n../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB\n../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB\n../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB\n../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB\n../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB\n../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB\n../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB\n../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB\n../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB\n../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB\n../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB\n../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB\n../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB\n../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB\n../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB\n../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB\n../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB\n../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB\n../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB\n../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB\n../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB\n../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB\n../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB\n../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB\n../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB\n../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB\n../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB\n../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB\n../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB\n../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB\n../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB\n../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB\n../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB\n../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB\n../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB\n../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB\n../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB\n../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB\n../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB\n../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB\n../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB\n../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB\n../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB\n../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB\n../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB\n../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB\n../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB\n../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB\n../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB\n../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB\n../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB\n../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB\n../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB\n../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB\n../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB\n../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB\n../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB\n../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB\n../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB\n../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB\n../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB\n../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB\n../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB\n../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB\n../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB\n../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB\n../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB\n../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB\n../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB\n../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB\n../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB\n../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB\n../public/vue-assets/assets/theme-Cy-WIInU.js 0.63 kB │ gzip: 0.42 kB │ map: 0.49 kB\n../public/vue-assets/assets/pick-BGRRe-Qj.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB\n../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB\n../public/vue-assets/assets/throttle-DmtOZ8h1.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB\n../public/vue-assets/assets/lastFilters-CzSBGyMt.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB\n../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gzip: 0.50 kB │ map: 1.64 kB\n../public/vue-assets/assets/v-focus-618yf9WO.js 0.85 kB │ gzip: 0.52 kB │ map: 1.42 kB\n../public/vue-assets/assets/ListLoader-bfQmkVGu.js 0.87 kB │ gzip: 0.54 kB │ map: 2.90 kB\n../public/vue-assets/assets/utils-CAMifZzY.js 0.88 kB │ gzip: 0.53 kB │ map: 2.45 kB\n../public/vue-assets/assets/mobileApp-QFLS3kId.js 0.89 kB │ gzip: 0.54 kB │ map: 1.12 kB\n../public/vue-assets/assets/pickBy-BtwCuAYd.js 0.95 kB │ gzip: 0.59 kB │ map: 2.57 kB\n../public/vue-assets/assets/BuildInfo-CIGre86L.js 1.00 kB │ gzip: 0.65 kB │ map: 1.48 kB\n../public/vue-assets/assets/LogoShort100-D_SQdBYB.js 1.01 kB │ gzip: 0.64 kB │ map: 1.23 kB\n../public/vue-assets/assets/useDrawerModal-CmhXI-pZ.js 1.04 kB │ gzip: 0.65 kB │ map: 1.94 kB\n../public/vue-assets/assets/_getAllKeysIn-CkMQAnJa.js 1.12 kB │ gzip: 0.67 kB │ map: 4.83 kB\n../public/vue-assets/assets/useAutosizeTextarea-DyMwh_20.js 1.13 kB │ gzip: 0.70 kB │ map: 3.16 kB\n../public/vue-assets/assets/planhat-DPA36Hcn.js 1.21 kB │ gzip: 0.71 kB │ map: 2.18 kB\n../public/vue-assets/assets/useStoreModule-Cx6UoGVJ.js 1.35 kB │ gzip: 0.72 kB │ map: 6.03 kB\n../public/vue-assets/assets/GenericMessage-BxGsrfvw.js 1.39 kB │ gzip: 0.75 kB │ map: 1.90 kB\n../public/vue-assets/assets/BrowserExtensionInstaller-DimyBPIi.js 1.45 kB │ gzip: 0.78 kB │ map: 2.05 kB\n../public/vue-assets/assets/debounce-DG3xxJjJ.js 1.53 kB │ gzip: 0.83 kB │ map: 8.61 kB\n../public/vue-assets/assets/extension-installed-mV_4t574.js 1.60 kB │ gzip: 0.91 kB │ map: 3.20 kB\n../public/vue-assets/assets/RecipientsCell-BS9gDGey.js 1.61 kB │ gzip: 0.93 kB │ map: 4.04 kB\n../public/vue-assets/assets/PrimaryButton-DaKR3UAG.js 1.61 kB │ gzip: 0.87 kB │ map: 3.73 kB\n../public/vue-assets/assets/KioskBanner-g60shJd4.js 1.66 kB │ gzip: 1.00 kB │ map: 2.88 kB\n../public/vue-assets/assets/LogoLong100-Hid0kvjR.js 1.78 kB │ gzip: 1.08 kB │ map: 5.91 kB\n../public/vue-assets/assets/GoogleLikeButton-CGFy3nbz.js 1.80 kB │ gzip: 0.84 kB │ map: 4.71 kB\n../public/vue-assets/assets/AppAlert-DFp0nftl.js 1.86 kB │ gzip: 1.01 kB │ map: 6.51 kB\n../public/vue-assets/assets/usePusherEventListener-Z27Z5klt.js 1.93 kB │ gzip: 1.08 kB │ map: 9.59 kB\n../public/vue-assets/assets/AppForm-BgtH5xsM.js 2.01 kB │ gzip: 1.10 kB │ map: 6.89 kB\n../public/vue-assets/assets/vee-validate-rules-IFeGZHb3.js 2.02 kB │ gzip: 0.89 kB │ map: 22.31 kB\n../public/vue-assets/assets/literals-CXSwYC8y.js 2.05 kB │ gzip: 0.97 kB │ map: 3.08 kB\n../public/vue-assets/assets/TabEmptyState-pk8vRxJt.js 2.16 kB │ gzip: 1.12 kB │ map: 8.26 kB\n../public/vue-assets/assets/Replies-Cn_qGwMd.js 2.23 kB │ gzip: 1.14 kB │ map: 2.40 kB\n../public/vue-assets/assets/settings-BSSIkavG.js 2.34 kB │ gzip: 1.24 kB │ map: 1.73 kB\n../public/vue-assets/assets/SeekBtn-CMp8sSUA.js 2.47 kB │ gzip: 1.18 kB │ map: 9.27 kB\n../public/vue-assets/assets/AiAutomation-C5_UlocO.js 2.59 kB │ gzip: 1.37 kB │ map: 4.45 kB\n../public/vue-assets/assets/locked-Bad3U1k5.js 2.59 kB │ gzip: 1.43 kB │ map: 4.00 kB\n../public/vue-assets/assets/DrawerWidget-BPC-tCgo.js 2.68 kB │ gzip: 1.33 kB │ map: 6.95 kB\n../public/vue-assets/assets/vue-infinite-scroll-D0cI4gH6.js 2.72 kB │ gzip: 1.28 kB │ map: 9.99 kB\n../public/vue-assets/assets/useActivityCustomerName-CYuaZj-p.js 2.87 kB │ gzip: 1.41 kB │ map: 6.27 kB\n../public/vue-assets/assets/other-D11UHzKP.js 2.97 kB │ gzip: 1.51 kB │ map: 3.38 kB\n../public/vue-assets/assets/InputDropdown-CBM8xiPT.js 3.33 kB │ gzip: 1.61 kB │ map: 6.02 kB\n../public/vue-assets/assets/AvatarsStack-hxex9Ic8.js 3.40 kB │ gzip: 1.51 kB │ map: 9.54 kB\n../public/vue-assets/assets/activity-preview-CoaCdIkx.js 3.45 kB │ gzip: 1.68 kB │ map: 10.11 kB\n../public/vue-assets/assets/FollowModal-SMYvVwqG.js 3.70 kB │ gzip: 1.81 kB │ map: 8.86 kB\n../public/vue-assets/assets/softphone-coach-C452yEnj.js 3.74 kB │ gzip: 1.96 kB │ map: 5.03 kB\n../public/vue-assets/assets/store-CloJVGCY.js 4.10 kB │ gzip: 2.00 kB │ map: 18.73 kB\n../public/vue-assets/assets/AiContext-DJ4M3rJ1.js 4.34 kB │ gzip: 2.08 kB │ map: 13.11 kB\n../public/vue-assets/assets/meeting-consent-B24mqvl1.js 4.43 kB │ gzip: 2.05 kB │ map: 9.72 kB\n../public/vue-assets/assets/vue-multiselect-VB2Agtp1.js 4.49 kB │ gzip: 1.93 kB │ map: 14.85 kB\n../public/vue-assets/assets/snackbarNotifications-DjDIGkWd.js 4.83 kB │ gzip: 1.58 kB │ map: 11.62 kB\n../public/vue-assets/assets/invitation-B5F0aLwl.js 4.88 kB │ gzip: 2.21 kB │ map: 19.38 kB\n../public/vue-assets/assets/textarea-caret-B2HdIdpZ.js 5.25 kB │ gzip: 2.41 kB │ map: 14.48 kB\n../public/vue-assets/assets/connect-DvCp38Q2.js 5.31 kB │ gzip: 2.31 kB │ map: 10.62 kB\n../public/vue-assets/assets/snackbar-Bq-YQ7pz.js 5.48 kB │ gzip: 2.37 kB │ map: 20.43 kB\n../public/vue-assets/assets/RadioField-2SeSZB7D.js 5.65 kB │ gzip: 2.22 kB │ map: 15.82 kB\n../public/vue-assets/assets/filters-D_eXZdIL.js 5.76 kB │ gzip: 2.17 kB │ map: 16.36 kB\n../public/vue-assets/assets/useActivityHelper-BvWVN0nz.js 5.84 kB │ gzip: 2.51 kB │ map: 14.26 kB\n../public/vue-assets/assets/vue-scrollto-ul3pFdrb.js 5.97 kB │ gzip: 2.72 kB │ map: 23.98 kB\n../public/vue-assets/assets/join-conference-CLdXMCwD.js 6.25 kB │ gzip: 2.83 kB │ map: 24.66 kB\n../public/vue-assets/assets/pluralize-BeKVJaE0.js 6.34 kB │ gzip: 2.70 kB │ map: 18.28 kB\n../public/vue-assets/assets/login-PrWVOMsr.js 7.02 kB │ gzip: 3.17 kB │ map: 17.51 kB\n../public/vue-assets/assets/AppLinks-Bg20Hslb.js 7.14 kB │ gzip: 2.80 kB │ map: 14.87 kB\n../public/vue-assets/assets/InputField-CkdrqKBp.js 7.20 kB │ gzip: 2.58 kB │ map: 19.39 kB\n../public/vue-assets/assets/UserAvatar-UKkSAS4R.js 7.93 kB │ gzip: 3.32 kB │ map: 34.91 kB\n../public/vue-assets/assets/InputText-BH9WFuby.js 7.99 kB │ gzip: 3.05 kB │ map: 20.64 kB\n../public/vue-assets/assets/AiCrmNotes-DmPJHAz_.js 8.27 kB │ gzip: 3.32 kB │ map: 34.03 kB\n../public/vue-assets/assets/vue-mq-CmpUzQtD.js 8.84 kB │ gzip: 3.54 kB │ map: 23.69 kB\n../public/vue-assets/assets/pro-duotone-svg-icons-BSBZV3-t.js 9.51 kB │ gzip: 3.43 kB │ map: 3,146.68 kB\n../public/vue-assets/assets/activity-preview-result-CQou30yT.js 10.65 kB │ gzip: 3.98 kB │ map: 38.51 kB\n../public/vue-assets/assets/pro-regular-svg-icons-CWpSBR20.js 13.10 kB │ gzip: 4.64 kB │ map: 3,178.15 kB\n../public/vue-assets/assets/add-to-playlist-modal-BS8w3ovp.js 14.99 kB │ gzip: 5.98 kB │ map: 51.34 kB\n../public/vue-assets/assets/ai-reports-Cy_xmRg8.js 15.17 kB │ gzip: 6.04 kB │ map: 51.85 kB\n../public/vue-assets/assets/export-portal-CZ2b-FlS.js 15.68 kB │ gzip: 6.22 kB │ map: 52.78 kB\n../public/vue-assets/assets/Comment-CdvjTszI.js 15.92 kB │ gzip: 5.72 kB │ map: 39.96 kB\n../public/vue-assets/assets/useragent-DQ4F_O30.js 18.02 kB │ gzip: 8.06 kB │ map: 68.31 kB\n../public/vue-assets/assets/linkify-B_q6MgwI.js 18.58 kB │ gzip: 10.37 kB │ map: 88.73 kB\n../public/vue-assets/assets/ai-reports-manage-B1v5HdqS.js 18.92 kB │ gzip: 6.76 kB │ map: 66.14 kB\n../public/vue-assets/assets/dist-C2hisF0L.js 19.32 kB │ gzip: 7.87 kB │ map: 390.77 kB\n../public/vue-assets/assets/pro-solid-svg-icons-DBOkpln3.js 19.46 kB │ gzip: 6.72 kB │ map: 2,692.14 kB\n../public/vue-assets/assets/purify.es-BxOw6oE6.js 21.49 kB │ gzip: 8.71 kB │ map: 83.43 kB\n../public/vue-assets/assets/ActionItems-uKCSfiLo.js 21.92 kB │ gzip: 8.55 kB │ map: 76.05 kB\n../public/vue-assets/assets/mobile-zCtNIOGN.js 23.34 kB │ gzip: 9.71 kB │ map: 50.90 kB\n../public/vue-assets/assets/basic-modal-BdXsnFwC.js 23.87 kB │ gzip: 9.06 kB │ map: 64.15 kB\n../public/vue-assets/assets/GridView-D5_z7YdA.js 26.60 kB │ gzip: 10.05 kB │ map: 92.74 kB\n../public/vue-assets/assets/ondemand-mxFxJiHI.js 26.88 kB │ gzip: 9.39 kB │ map: 73.94 kB\n../public/vue-assets/assets/CrmLink-DKYsnHnx.js 27.91 kB │ gzip: 10.18 kB │ map: 93.18 kB\n../public/vue-assets/assets/liquor-tree-COUefof4.js 30.75 kB │ gzip: 9.58 kB │ map: 78.74 kB\n../public/vue-assets/assets/DealRiskList-D7gUVql5.js 34.39 kB │ gzip: 10.62 kB │ map: 115.18 kB\n../public/vue-assets/assets/AskAnything-DgI0NfRA.js 39.50 kB │ gzip: 14.97 kB │ map: 173.20 kB\n../public/vue-assets/assets/lib-CwM9toD2.js 39.69 kB │ gzip: 12.70 kB │ map: 138.34 kB\n../public/vue-assets/assets/AppFormField-BqQiLGFF.js 41.91 kB │ gzip: 12.69 kB │ map: 150.73 kB\n../public/vue-assets/assets/deal-view-D4YlPwr_.js 43.22 kB │ gzip: 14.35 kB │ map: 150.62 kB\n../public/vue-assets/assets/exports-D1lmea4O.js 47.84 kB │ gzip: 16.46 kB │ map: 294.48 kB\n../public/vue-assets/assets/playlists-BWAdERcJ.js 48.28 kB │ gzip: 15.07 kB │ map: 153.25 kB\n../public/vue-assets/assets/callScoringTemplates-zeRn40uL.js 55.13 kB │ gzip: 13.28 kB │ map: 65.85 kB\n../public/vue-assets/assets/_copyObject-USkOnlaQ.js 61.28 kB │ gzip: 20.09 kB │ map: 239.59 kB\n../public/vue-assets/assets/pusher-znYCfz7U.js 62.98 kB │ gzip: 18.88 kB │ map: 219.27 kB\n../public/vue-assets/assets/onboard-CyAPGoFk.js 63.11 kB │ gzip: 21.85 kB │ map: 201.38 kB\n../public/vue-assets/assets/StatusBadge-DNHiCr2i.js 64.66 kB │ gzip: 22.96 kB │ map: 244.72 kB\n../public/vue-assets/assets/kiosk-dfcpodo5.js 79.60 kB │ gzip: 22.65 kB │ map: 300.68 kB\n../public/vue-assets/assets/preload-helper-DCvhahzG.js 82.59 kB │ gzip: 27.46 kB │ map: 3,452.35 kB\n../public/vue-assets/assets/deal-insights-BVnPilVP.js 94.84 kB │ gzip: 28.17 kB │ map: 292.79 kB\n../public/vue-assets/assets/ListView-DJD6SV4A.js 115.71 kB │ gzip: 33.79 kB │ map: 308.10 kB\n../public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js 117.59 kB │ gzip: 38.71 kB │ map: 500.60 kB\n../public/vue-assets/assets/WelcomeLayout-B6wd32HG.js 120.67 kB │ gzip: 34.16 kB │ map: 258.56 kB\n../public/vue-assets/assets/dashboard-CsDOiLAi.js 128.71 kB │ gzip: 40.05 kB │ map: 410.48 kB\n../public/vue-assets/assets/emoji-input-CSq87OVy.js 129.28 kB │ gzip: 36.72 kB │ map: 266.15 kB\n../public/vue-assets/assets/AppButton-D3qMdODr.js 133.44 kB │ gzip: 43.03 kB │ map: 516.67 kB\n../public/vue-assets/assets/sentry-B3B1ZM6O.js 164.28 kB │ gzip: 52.24 kB │ map: 831.82 kB\n../public/vue-assets/assets/OrgSettingsLayout-DatDldIe.js 176.33 kB │ gzip: 56.15 kB │ map: 623.43 kB\n../public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js 180.40 kB │ gzip: 67.85 kB │ map: 836.88 kB\n../public/vue-assets/assets/playback-D1gm80qQ.js 198.79 kB │ gzip: 61.85 kB │ map: 684.87 kB\n../public/vue-assets/assets/index.module-Bjlhgfd1.js 218.14 kB │ gzip: 64.16 kB │ map: 1,108.20 kB\n../public/vue-assets/assets/intl-tel-input-BW4mv40Q.js 264.94 kB │ gzip: 60.31 kB │ map: 475.61 kB\n../public/vue-assets/assets/team-insights-DRugjYCA.js 298.57 kB │ gzip: 77.22 kB │ map: 959.96 kB\n../public/vue-assets/assets/popper-CQwVcrX4.js 307.13 kB │ gzip: 103.86 kB │ map: 1,245.28 kB\n../public/vue-assets/assets/PhoneField-CwCIoAYm.js 343.99 kB │ gzip: 84.90 kB │ map: 849.05 kB\n../public/vue-assets/assets/live-CxSmZv7h.js 367.43 kB │ gzip: 97.05 kB │ map: 792.41 kB\n../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BNO485xV.js 689.63 kB │ gzip: 202.81 kB │ map: 3,016.64 kB\n../public/vue-assets/assets/index-Cp0YOK4U.js 825.23 kB │ gzip: 72.54 kB │ map: 436.62 kB\n../public/vue-assets/assets/logged-in-layout-CE9ox17M.js 1,402.70 kB │ gzip: 438.07 kB │ map: 6,283.55 kB\n\n✓ built in 26.01s\n[plugin builtin:vite-reporter] \n(!) Some chunks are larger than 500 kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting\n- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.\nlukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-token-auth-response-change) $","is_focused":true},{"role":"AXRadioButton","text":"DOCKER","depth":2,"bounds":{"left":0.00069444446,"top":0.06,"width":0.12291667,"height":0.026666667},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.0048611113,"top":0.064444445,"width":0.011111111,"height":0.017777778},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"DEV (docker)","depth":2,"bounds":{"left":0.12361111,"top":0.06,"width":0.12291667,"height":0.026666667},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.12777779,"top":0.064444445,"width":0.011111111,"height":0.017777778},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"APP (-zsh)","depth":2,"bounds":{"left":0.24652778,"top":0.06,"width":0.12291667,"height":0.026666667},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.25069445,"top":0.064444445,"width":0.011111111,"height":0.017777778},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.36944443,"top":0.06,"width":0.12291667,"height":0.026666667},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.37361112,"top":0.064444445,"width":0.011111111,"height":0.017777778},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"-zsh","depth":2,"bounds":{"left":0.4923611,"top":0.06,"width":0.12291667,"height":0.026666667},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.4965278,"top":0.064444445,"width":0.011111111,"height":0.017777778},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"✳ Review screenpipe usage and Boosteroid integration (claude)","depth":2,"bounds":{"left":0.61527777,"top":0.06,"width":0.12291667,"height":0.026666667},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.61944443,"top":0.064444445,"width":0.011111111,"height":0.017777778},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"ec2-user@ip-10-30-159-186:~ (nc)","depth":2,"bounds":{"left":0.73819447,"top":0.06,"width":0.12291667,"height":0.026666667},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.7423611,"top":0.064444445,"width":0.011111111,"height":0.017777778},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"ec2-user@ip-10-20-6-111:~ (nc)","depth":2,"bounds":{"left":0.8611111,"top":0.06,"width":0.12291667,"height":0.026666667},"role_description":"radio button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close Tab","depth":3,"bounds":{"left":0.86527777,"top":0.064444445,"width":0.011111111,"height":0.017777778},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"⌥⌘1","depth":1,"bounds":{"left":0.95555556,"top":0.033333335,"width":0.03888889,"height":0.018888889},"automation_id":"_NS:8","role_description":"text"},{"role":"AXStaticText","text":"APP (-zsh)","depth":1,"bounds":{"left":0.475,"top":0.034444444,"width":0.05138889,"height":0.017777778},"role_description":"text"}]...
|
-2407191479157132203
|
3429803486563842285
|
idle
|
accessibility
|
NULL
|
info Visit [URL_WITH_CREDENTIALS] ~/jiminny/app/fr info Visit [URL_WITH_CREDENTIALS] ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yanrn build
zsh: command not found: yanrn
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn build
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚡️ secrets for agents: [URL_WITH_CREDENTIALS] ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn install
➤ YN0000: · Yarn 4.12.0
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed
➤ YN0000: ┌ Post-resolution validation
➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide @testing-library/dom (pea6ced), requested by @testing-library/user-event.
➤ YN0002: │ root-workspace-0b6124@workspace:. doesn't provide noty (p5bdb0d), requested by vue-components.
➤ YN0086: │ Some peer dependencies are incorrectly met by your project; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code.
➤ YN0086: │ Some peer dependencies are incorrectly met by dependencies; run yarn explain peer-requirements for details.
➤ YN0000: └ Completed
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed in 1s 655ms
➤ YN0000: ┌ Link step
➤ YN0008: │ root-workspace-0b6124@workspace:. must be rebuilt because its dependency tree changed
➤ YN0000: └ Completed in 0s 969ms
➤ YN0000: · Done with warnings in 3s 14ms
lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $ yarn build
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️ override existing env vars with { override: true }
vite v8.0.0 building client environment for production...
✓ 4656 modules transformed.
[sentry-vite-plugin] Warning: No auth token provided. Will not create release. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/
[sentry-vite-plugin] Warning: No auth token provided. Will not upload source maps. Please set the `authToken` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/
computing gzip size...
../public/vue-assets/index.html 4.58 kB │ gzip: 1.15 kB
../public/vue-assets/assets/job-adder-B2LcgC4o.png 5.41 kB
../public/vue-assets/assets/dixa-DzT89tKh.png 7.87 kB
../public/vue-assets/assets/planhat-CQycOTMW.svg 8.61 kB │ gzip: 3.48 kB
../public/vue-assets/assets/funding-circle-9iGnDGsz.png 9.43 kB
../public/vue-assets/assets/cision-uOdx_YiN.svg 14.41 kB │ gzip: 6.32 kB
../public/vue-assets/assets/les-mills-DWabpmYc.png 15.73 kB
../public/vue-assets/assets/superside-btT37L9L.png 26.69 kB
../public/vue-assets/assets/flags-a2kmUSbF.webp 28.18 kB
../public/vue-assets/assets/quinyx-RGQNHx6o.png 63.17 kB
../public/vue-assets/assets/[EMAIL] 66.44 kB
../public/vue-assets/assets/bg-marketing-CAIHIJMj.png 70.66 kB
../public/vue-assets/.vite/manifest.json 85.73 kB │ gzip: 8.32 kB
../public/vue-assets/assets/jiminny-score-DtTbKZaD.svg 131.93 kB │ gzip: 86.07 kB
../public/vue-assets/assets/wavy-bg-vnCaCm9m.webm 670.97 kB
../public/vue-assets/assets/wavy-bg-Op6dRIjR.mp4 14,484.63 kB
../public/vue-assets/assets/AppForm-EEGPL5K8.css 0.04 kB │ gzip: 0.06 kB
../public/vue-assets/assets/RecipientsCell-DNOSS8k1.css 0.12 kB │ gzip: 0.12 kB
../public/vue-assets/assets/softphone-coach-Cy_9nuQZ.css 0.13 kB │ gzip: 0.10 kB
../public/vue-assets/assets/locked-CHS8VPur.css 0.15 kB │ gzip: 0.12 kB
../public/vue-assets/assets/mobile-KPnGhnTp.css 0.16 kB │ gzip: 0.14 kB
../public/vue-assets/assets/BuildInfo-CxNQv_OV.css 0.20 kB │ gzip: 0.17 kB
../public/vue-assets/assets/AvatarsStack-C0Nvfh1V.css 0.28 kB │ gzip: 0.20 kB
../public/vue-assets/assets/LogoLong100-ByQTvUY3.css 0.32 kB │ gzip: 0.20 kB
../public/vue-assets/assets/connect--xBDzLbc.css 0.34 kB │ gzip: 0.21 kB
../public/vue-assets/assets/KioskBanner-xU3FRd8g.css 0.41 kB │ gzip: 0.27 kB
../public/vue-assets/assets/extension-installed-BPBhG13P.css 0.41 kB │ gzip: 0.26 kB
../public/vue-assets/assets/FollowModal-A0rJmIOK.css 0.45 kB │ gzip: 0.23 kB
../public/vue-assets/assets/GenericMessage-DutAlObK.css 0.49 kB │ gzip: 0.26 kB
../public/vue-assets/assets/textarea-caret-DCiNUER_.css 0.51 kB │ gzip: 0.32 kB
../public/vue-assets/assets/AppLinks-BznfGcBR.css 0.58 kB │ gzip: 0.33 kB
../public/vue-assets/assets/SeekBtn-_VMPIk6v.css 0.63 kB │ gzip: 0.32 kB
../public/vue-assets/assets/emoji-input-kJWRbWf8.css 0.68 kB │ gzip: 0.38 kB
../public/vue-assets/assets/activity-preview-BDxP2S0-.css 0.70 kB │ gzip: 0.41 kB
../public/vue-assets/assets/ListLoader-DQqAw-8s.css 0.73 kB │ gzip: 0.38 kB
../public/vue-assets/assets/filters-Bgb6cQD6.css 0.75 kB │ gzip: 0.39 kB
../public/vue-assets/assets/AiContext-Bg-zjjbA.css 0.99 kB │ gzip: 0.45 kB
../public/vue-assets/assets/vue3-daterange-picker-izPOBj3P.css 1.02 kB │ gzip: 0.39 kB
../public/vue-assets/assets/PrimaryButton-CJj2FzKS.css 1.08 kB │ gzip: 0.34 kB
../public/vue-assets/assets/other-BTuPXtu_.css 1.15 kB │ gzip: 0.49 kB
../public/vue-assets/assets/jenesius-vue-modal-DDcfejHO.css 1.17 kB │ gzip: 0.48 kB
../public/vue-assets/assets/TabEmptyState-DOlIO68k.css 1.21 kB │ gzip: 0.53 kB
../public/vue-assets/assets/AppAlert-BlSJKiqj.css 1.29 kB │ gzip: 0.41 kB
../public/vue-assets/assets/useActivityCustomerName-CBjfIUfJ.css 1.42 kB │ gzip: 0.45 kB
../public/vue-assets/assets/UserAvatar-co8l9mMk.css 1.51 kB │ gzip: 0.49 kB
../public/vue-assets/assets/basic-modal-Dx7ZBbcA.css 1.55 kB │ gzip: 0.66 kB
../public/vue-assets/assets/login-DYbcBesM.css 1.58 kB │ gzip: 0.61 kB
../public/vue-assets/assets/DrawerWidget-poAmqspk.css 1.67 kB │ gzip: 0.69 kB
../public/vue-assets/assets/ActionItems-5FkZSo3G.css 1.79 kB │ gzip: 0.80 kB
../public/vue-assets/assets/join-conference-DQ6Yl7eU.css 1.82 kB │ gzip: 0.75 kB
../public/vue-assets/assets/InputText-C-DxDNSV.css 1.95 kB │ gzip: 0.71 kB
../public/vue-assets/assets/GoogleLikeButton-DvQHxbqR.css 2.11 kB │ gzip: 0.66 kB
../public/vue-assets/assets/usePusherEventListener-CDj8aSNp.css 2.20 kB │ gzip: 0.73 kB
../public/vue-assets/assets/onboard-IzGiQ-EC.css 2.32 kB │ gzip: 0.95 kB
../public/vue-assets/assets/ai-reports-manage-DaynTl62.css 2.34 kB │ gzip: 0.86 kB
../public/vue-assets/assets/StatusBadge-B4N12dzU.css 2.35 kB │ gzip: 0.86 kB
../public/vue-assets/assets/GridView-CsP1Jk-k.css 2.36 kB │ gzip: 0.90 kB
../public/vue-assets/assets/WelcomeLayout-6AX86p6F.css 2.38 kB │ gzip: 0.91 kB
../public/vue-assets/assets/snackbar-CS_iqvrv.css 2.45 kB │ gzip: 0.80 kB
../public/vue-assets/assets/ai-reports-mtqGqPPq.css 2.47 kB │ gzip: 0.91 kB
../public/vue-assets/assets/Comment-gmAfiuer.css 2.63 kB │ gzip: 1.00 kB
../public/vue-assets/assets/meeting-consent-BasRvxE3.css 2.66 kB │ gzip: 0.96 kB
../public/vue-assets/assets/DealRiskList-CwxmDnSC.css 2.67 kB │ gzip: 0.96 kB
../public/vue-assets/assets/add-to-playlist-modal-C_ad1hht.css 2.84 kB │ gzip: 0.95 kB
../public/vue-assets/assets/live-_zT5qBc1.css 3.60 kB │ gzip: 1.16 kB
../public/vue-assets/assets/RadioField-DDp8Y71G.css 3.64 kB │ gzip: 1.20 kB
../public/vue-assets/assets/vue-multiselect-BkQNV7oL.css 3.80 kB │ gzip: 0.86 kB
../public/vue-assets/assets/activity-preview-result-Db1Da81T.css 3.89 kB │ gzip: 1.15 kB
../public/vue-assets/assets/liquor-tree-CB5oh8v1.css 4.08 kB │ gzip: 1.24 kB
../public/vue-assets/assets/sentry-CSjHcvmn.css 4.47 kB │ gzip: 1.08 kB
../public/vue-assets/assets/AiAutomation-Cj1t8v5y.css 4.61 kB │ gzip: 0.84 kB
../public/vue-assets/assets/export-portal-CyIUVTEe.css 5.34 kB │ gzip: 1.65 kB
../public/vue-assets/assets/InputField-C4hoKJ7Z.css 6.13 kB │ gzip: 1.27 kB
../public/vue-assets/assets/vue-mq-bh4L87Tr.css 6.64 kB │ gzip: 1.95 kB
../public/vue-assets/assets/invitation-EPR1t-bH.css 6.74 kB │ gzip: 2.22 kB
../public/vue-assets/assets/ondemand-C2m0YVGA.css 6.84 kB │ gzip: 2.02 kB
../public/vue-assets/assets/AskAnything-CyvEhHS1.css 8.60 kB │ gzip: 2.60 kB
../public/vue-assets/assets/AppButton-BIeoar_U.css 8.88 kB │ gzip: 2.04 kB
../public/vue-assets/assets/kiosk-BcheyWWL.css 9.56 kB │ gzip: 2.53 kB
../public/vue-assets/assets/AiCrmNotes-nNTe_mOY.css 10.62 kB │ gzip: 1.93 kB
../public/vue-assets/assets/deal-view-DJzG7PLp.css 11.70 kB │ gzip: 3.29 kB
../public/vue-assets/assets/tokens-DZgWrfKd.css 12.44 kB │ gzip: 2.82 kB
../public/vue-assets/assets/tokens-DL2BPbai.css 12.89 kB │ gzip: 2.87 kB
../public/vue-assets/assets/playlists-Cy3t3kYU.css 13.54 kB │ gzip: 3.16 kB
../public/vue-assets/assets/PhoneField-D_kGOah0.css 13.75 kB │ gzip: 3.44 kB
../public/vue-assets/assets/ListView-Dt0qkyuY.css 17.07 kB │ gzip: 4.11 kB
../public/vue-assets/assets/intl-tel-input-DgmgTINs.css 17.11 kB │ gzip: 5.37 kB
../public/vue-assets/assets/AppFormField-DvpfRzi8.css 18.98 kB │ gzip: 4.42 kB
../public/vue-assets/assets/OrgSettingsLayout-BogdXtgY.css 21.98 kB │ gzip: 5.51 kB
../public/vue-assets/assets/dashboard-DQw3TKyk.css 22.74 kB │ gzip: 4.35 kB
../public/vue-assets/assets/deal-insights-CfX3UNzh.css 29.66 kB │ gzip: 6.44 kB
../public/vue-assets/assets/team-insights-CjVhm0JN.css 42.31 kB │ gzip: 8.46 kB
../public/vue-assets/assets/playback-CvJP5tX1.css 44.55 kB │ gzip: 10.36 kB
../public/vue-assets/assets/video-js-skin-DYZluGb-.css 47.73 kB │ gzip: 12.63 kB
../public/vue-assets/assets/assets-CAbfI4CY.css 83.38 kB │ gzip: 51.71 kB
../public/vue-assets/assets/logged-in-layout-1mAqkmnS.css 153.67 kB │ gzip: 27.18 kB
../public/vue-assets/assets/assets-xH6dx_9q.css 259.71 kB │ gzip: 181.71 kB
../public/vue-assets/assets/directives-DJJeJJOP.js 0.53 kB │ gzip: 0.36 kB │ map: 0.32 kB
../public/vue-assets/assets/jenesius-vue-modal-BuBhyl83.js 0.54 kB │ gzip: 0.37 kB │ map: 0.47 kB
../public/vue-assets/assets/spark-D_-Wgfar.js 0.54 kB │ gzip: 0.35 kB │ map: 0.40 kB
../public/vue-assets/assets/url-messenger-_CGQa-lH.js 0.56 kB │ gzip: 0.37 kB │ map: 0.46 kB
../public/vue-assets/assets/wavy-bg-Cec-_GDj.js 0.57 kB │ gzip: 0.36 kB │ map: 0.35 kB
../public/vue-assets/assets/component-css-class-CtO0AVgW.js 0.61 kB │ gzip: 0.40 kB │ map: 0.91 kB
../public/vue-assets/assets/theme-B5VdyMN_.js 0.63 kB │ gzip: 0.41 kB │ map: 0.49 kB
../public/vue-assets/assets/pick-C8Pw7kHx.js 0.71 kB │ gzip: 0.45 kB │ map: 1.59 kB
../public/vue-assets/assets/utils-BjsEoLDB.js 0.77 kB │ gzip: 0.50 kB │ map: 1.68 kB
../public/vue-assets/assets/throttle-siTOKEMt.js 0.78 kB │ gzip: 0.49 kB │ map: 3.24 kB
../public/vue-assets/assets/lastFilters-B_B_O5LY.js 0.80 kB │ gzip: 0.51 kB │ map: 1.12 kB
../public/vue-assets/assets/useAuthState-Bpx8WpBc.js 0.81 kB │ gz...
|
46615
|
|
46618
|
984
|
0
|
2026-04-17T10:42:32.672552+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422552672_m2.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/onboard
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Connected
Connected
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Clear the Web Console output (⌘K, Ctrl+L)
IntegrationApp
IntegrationApp
115 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Top
Switch to multi-line editor mode (Cmd + B)
...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.31666666,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.3402778,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Update your information","depth":9,"bounds":{"left":0.29335937,"top":0.33888888,"width":0.15273437,"height":0.016666668},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Update your information","depth":10,"bounds":{"left":0.31796876,"top":0.33680555,"width":0.103515625,"height":0.020833334},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GENERAL","depth":10,"bounds":{"left":0.29335937,"top":0.37083334,"width":0.025,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"TIMEZONE","depth":12,"bounds":{"left":0.2984375,"top":0.3986111,"width":0.0203125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option Europe/Sofia (UTC +03:00)","depth":10,"bounds":{"left":0.2984375,"top":0.40763888,"width":0.14726563,"height":0.017361112},"value":"Select option Europe/Sofia (UTC +03:00)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Europe/Sofia (UTC +03:00)","depth":12,"bounds":{"left":0.2984375,"top":0.41041666,"width":0.061328124,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"bounds":{"left":0.44023436,"top":0.39375,"width":0.003125,"height":0.017361112},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"LANGUAGES SPOKEN DURING CALLS","depth":10,"bounds":{"left":0.29335937,"top":0.44930556,"width":0.09609375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEFAULT SPOKEN LANGUAGE","depth":12,"bounds":{"left":0.2984375,"top":0.47708333,"width":0.05546875,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option English (United Kingdom)","depth":10,"bounds":{"left":0.2984375,"top":0.4861111,"width":0.14726563,"height":0.017361112},"value":"Select option English (United Kingdom)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"English (United Kingdom)","depth":12,"bounds":{"left":0.2984375,"top":0.4888889,"width":0.057421874,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"bounds":{"left":0.44023436,"top":0.4722222,"width":0.003125,"height":0.017361112},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"If the language isn't detected we'll default to this one","depth":11,"bounds":{"left":0.29335937,"top":0.5090278,"width":0.109375,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Add language","depth":11,"bounds":{"left":0.29335937,"top":0.5298611,"width":0.037890624,"height":0.013888889},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CONNECT/SYNC SETTINGS","depth":10,"bounds":{"left":0.29335937,"top":0.5659722,"width":0.06992187,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Connect Zoho CRM","depth":11,"bounds":{"left":0.29335937,"top":0.59166664,"width":0.0546875,"height":0.013888889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"zohocrm Connected","depth":10,"bounds":{"left":0.3765625,"top":0.5861111,"width":0.06953125,"height":0.025},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connected","depth":11,"bounds":{"left":0.40429688,"top":0.5923611,"width":0.026171874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Import Calendar Meetings","depth":11,"bounds":{"left":0.29335937,"top":0.62777776,"width":0.07304688,"height":0.013888889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":12,"bounds":{"left":0.365625,"top":0.62430555,"width":0.003515625,"height":0.017361112},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"google Sign in with Google","depth":10,"bounds":{"left":0.3765625,"top":0.62222224,"width":0.06953125,"height":0.025},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sign in with Google","depth":11,"bounds":{"left":0.39414063,"top":0.6284722,"width":0.046484374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Let's Get Started!","depth":9,"bounds":{"left":0.3347656,"top":0.68194443,"width":0.06992187,"height":0.025},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Clear the Web Console output (⌘K, Ctrl+L)","depth":15,"bounds":{"left":0.46328124,"top":0.068055555,"width":0.01015625,"height":0.013888889},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXTextField","text":"IntegrationApp","depth":15,"bounds":{"left":0.47578126,"top":0.065972224,"width":0.33007812,"height":0.018055556},"value":"IntegrationApp","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"IntegrationApp","depth":16,"bounds":{"left":0.484375,"top":0.07013889,"width":0.03046875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"115 hidden","depth":16,"bounds":{"left":0.80742186,"top":0.07013889,"width":0.021875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Clear filter input","depth":15,"bounds":{"left":0.83085936,"top":0.06944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Errors","depth":15,"bounds":{"left":0.8417969,"top":0.068055555,"width":0.0171875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Warnings","depth":15,"bounds":{"left":0.85976565,"top":0.068055555,"width":0.023828125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Info","depth":15,"bounds":{"left":0.884375,"top":0.068055555,"width":0.0125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Logs","depth":15,"bounds":{"left":0.89765626,"top":0.068055555,"width":0.014453125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Debug","depth":15,"bounds":{"left":0.9128906,"top":0.068055555,"width":0.01796875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"CSS","depth":15,"bounds":{"left":0.9359375,"top":0.068055555,"width":0.01328125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"XHR","depth":15,"bounds":{"left":0.95,"top":0.068055555,"width":0.013671875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Requests","depth":15,"bounds":{"left":0.9644531,"top":0.068055555,"width":0.023828125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Console Settings","depth":15,"bounds":{"left":0.9898437,"top":0.06527778,"width":0.01015625,"height":0.019444445},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Top","depth":16,"bounds":{"left":0.97265625,"top":0.088194445,"width":0.016796876,"height":0.011111111},"help_text":"Select evaluation context","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Switch to multi-line editor mode (Cmd + B)","depth":16,"bounds":{"left":0.9898437,"top":0.08680555,"width":0.01015625,"height":0.013888889},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":18,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
1636502047254827797
|
-7388332033941292852
|
visual_change
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Connected
Connected
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Clear the Web Console output (⌘K, Ctrl+L)
IntegrationApp
IntegrationApp
115 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Top
Switch to multi-line editor mode (Cmd + B)
...
|
46616
|
|
46619
|
983
|
0
|
2026-04-17T10:42:34.552630+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422554552_m1.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/onboard
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Connected
Connected
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Clear the Web Console output (⌘K, Ctrl+L)
IntegrationApp
IntegrationApp
115 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Top
Switch to multi-line editor mode (Cmd + B)
...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Update your information","depth":9,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Update your information","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GENERAL","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"TIMEZONE","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option Europe/Sofia (UTC +03:00)","depth":10,"value":"Select option Europe/Sofia (UTC +03:00)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Europe/Sofia (UTC +03:00)","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"LANGUAGES SPOKEN DURING CALLS","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEFAULT SPOKEN LANGUAGE","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option English (United Kingdom)","depth":10,"value":"Select option English (United Kingdom)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"English (United Kingdom)","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"If the language isn't detected we'll default to this one","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Add language","depth":11,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CONNECT/SYNC SETTINGS","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Connect Zoho CRM","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"zohocrm Connected","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connected","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Import Calendar Meetings","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"google Sign in with Google","depth":10,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sign in with Google","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Let's Get Started!","depth":9,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Clear the Web Console output (⌘K, Ctrl+L)","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXTextField","text":"IntegrationApp","depth":15,"value":"IntegrationApp","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"IntegrationApp","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"115 hidden","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Clear filter input","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Errors","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Warnings","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Info","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Logs","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Debug","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"CSS","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"XHR","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Requests","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Console Settings","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Top","depth":16,"help_text":"Select evaluation context","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Switch to multi-line editor mode (Cmd + B)","depth":16,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":18,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
1636502047254827797
|
-7388332033941292852
|
visual_change
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Connected
Connected
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Clear the Web Console output (⌘K, Ctrl+L)
IntegrationApp
IntegrationApp
115 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Top
Switch to multi-line editor mode (Cmd + B)
...
|
NULL
|
|
46772
|
NULL
|
0
|
2026-04-17T10:47:39.299823+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422859299_m2.jpg...
|
PhpStorm
|
faVsco.js – SF [jiminny@localhost]
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.03046875,"top":0.017361112,"width":0.0453125,"height":0.022222223},"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"bounds":{"left":0.07578125,"top":0.017361112,"width":0.15898438,"height":0.022222223},"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.78515625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"bounds":{"left":0.803125,"top":0.017361112,"width":0.09765625,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9007813,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9140625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9273437,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96015626,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9734375,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9867188,"top":0.017361112,"width":0.013281226,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.12382813,"top":0.22083333,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.13867188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"bounds":{"left":0.1515625,"top":0.22013889,"width":0.0515625,"height":0.013888889},"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.21367188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.22539063,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7665353928652150759
|
-7771723620485485626
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY].php-cs-fixer.dist.phpphp.phpstorm.meta.php=.phpunit.result.cacheE.prettierignoreE windsurfrulespip _lde_nelper.pnppnpce neloermoces.onepnp aruisani composer.isonO composer.lockdependency-checker.jsonO dev.jsonE ids.txt=infection.json.distM-INSALL.mdM+ INTERNAL WEBHOOK SETUPjiminny_storageM+ licenses.mdM MakefileOpackage-lock.json= phpstan.neon.dist= phpstan-baseline.neon< phpunit.xmlTa raw_sqLquery.sqlM+ README.mdsonar-project.properties= test.py<> Untitled Diagram.xmlI5 vetur.config.jsM-+ WEbnOOK HILIEKING_IMPLE› Iib External Librariesv E® Scratches and Consolesv D Database Consoles© AutomatedReportsService.php© SendReportJob.phpC ReportController.phplokenbullaer.onoc leamsetuocontroller.onp• Filesystem.php© Team.php© RequestGenerateReportJob.phpT InteractsWithPivotTable.phg© CreateHeldActivityEvent.phpOpportunitySyncTrait.phpC OpportunityUpdated.php© SendReportMailJob.phpphp api.php© TrackProviderInstalledEvent.phpC Opportunity.phpC OpportunityStageUpdated.phpc) FventService?rovider.onn© RunOpportunityAiAnalysis.php( ImportBatchJobTrait.php© OpportunityPendingAiAnalysisAfterStageChanged.php© ProcessAiAutomationAnalysisResults.php(C) Service.php© ImportOpportunityBatch.php101819281030cachedStagesCcW165trait OpportunitySyncTraitA33 X2 X19 A Y 166private function resolveForecastCategory(?string $forecastCategory): stringf...1672 usages=169private function importExternalFieldData(array $properties, int $opportunitylra, 170171$crmFields = $this->getOpportunitySyncableFieldsO;=172$this->import0pportunityCrmFieldData(Sproperties, $crmFields, Sopportunityi17310331034103510481049105010511052Lusaeesprivate function importOpportunityContacts(Opportunity Sopportunity, array $as:177/*** Sync opportunity contacts using differential approach* This compares current vs new associations and only makes necessary changes=175176=1791801811821 usageprivate function syncOpportunityContactsDifferential(Opportunity $opportunity,1070private function getcurrentContactCrmIds(Opportunity $opportunity): array{...7 187A console [EU]4 DEAL RISKS [EU]A DI [EU]dEuleUv& jiminny@localhost& console yiminny @localrA DI [jiminny@localhost]4 HS_local [jiminny@localA SF [jiminny@localhost]A zoho_dev [jiminny@loceY A PRODД0/110771078107910801 usageprivate function logContactAssociationChanges(Opportunity Sopportunity,array $currentContactCrmIds,array $contactAssociations,array $contactsToAdd,array +concacustokemove): void {...}-189190191192—193services+,o,cv D DatabasevdtuA console 1 s 59 msu crm_contigurations 1s 391 msv & minnvo ocanost4SF4 HS_localV A PROD4 console 1 s 806 msV A STAGING& consoleOutputiD # 1695 X3 rowsS9T2_ ICIsImtpzC16l7VmNwrhzGFKLT0wzDKtNDLKNy04ZWI2LTAZNmNLM.FQG0A• expires Y177633617617296136151776509176I refresh_token_expires Y3 rows retrieved starting from 1 in 430 ms (execution: 40 ms, fetching: 390 ms)lablf Support Daily • in 1h 13 mAAutomatedRenortsCommandTest100% 145Fri 17 Apr 13:47:38= custom.log< Hs local liminnyalocalnostA console [PROD]E laravel.logA SF [jiminny@localhost] XC scratch_1.jsonA console (EU]© CrmEntityRepository.phpA console [STAGING]V connect.vuefi crm_configurations (EU]V Onboard.vueCascadeAutomated Report RetrDebugging OpportunitUpdate Connection Loconnect.vue tront-end/src/components/connecXAutovPlaygroundSELECT * FROM automated_reports order by za desc;SELECT * FROMautomated_report_results order by id desc;select * from activity_searches where user_id = 143;select * from ask_anything_prompts;ma liminnvvM09412 X2 X4AVnothing is therew"cant see log'sSELECT * FROM groups WHERE id = 1439;SELECT * FROM users WHERE group_id = 1439;select * from permissions; # 158select * from roles;select * from permission_role,The console is full of CSP warnings and errors but none of your [IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check:1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? — you may be running a stale build that doesn't include your changesselect * from teams where id = 1;select * from groups g JOIN playbooks p 1.n<->1: on g.playbook_id = p.id where g.team_id = 1;select * from groups where id = 28;select * from playbooks where team_id = 1;select * from playbooks where id = 179;select * from playbook_categories where id = 1391;select * from users where id = 143;select * from crm_profiles where user_id = 143;select * from activities where crm_configuration_id = 39 and type = 'conference"and crm_provider_id IS NOT NULL ORDER by id desc;select * from activities where id = 422003; # 00U0400000pB6FpMACSearched.intecrationAoo@nClickin tront-enc/src/cents/connect/connect.vue (2)The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44• connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [Integratlonado incecrac1onApouncllck called arter cllckine tne outton, tne dev server nasn't olckea up tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).SELECT ar.ig, ar.wuig, ar.mediantxpe, ar.status, a.txReFROM automated_report_results arJOIN automated_reports a ON a.id = ar.repontaidWHERE a.IxRe = 'ask_iiminnx'LIMIT 10;select * from teams where id = 3143;select * from crm_configurations where id = 500;select * from users where name = 'Integration Account'; # 1695SELECT * FROM social_accounts WHERE sociable_id = 1695;etI to CascadeAsk anything (284L)+ <> Code Claude Sonnet 4.6. provider Yu cooqle<null> zoom-phone<null> integration-app! state Ytuu-retresnfull-refreshfull-refreshWauth_scope Yopenid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/calendar http.phone:read:admin user:read:admin<null>• :-CSV vДOB,retry_after Y00 cr2020<nul><null>20242026-W Windsurf Teams 193:1 0 UTF-84 spaces...
|
46771
|
|
46773
|
NULL
|
0
|
2026-04-17T10:47:39.696274+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422859696_m1.jpg...
|
PhpStorm
|
faVsco.js – SF [jiminny@localhost]
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelplall= Support Daily - in 1 h 13 m100% <47APP (-zsh)X4-zshDOCKER• ₴1DEV (docker)• *2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-mxFxJiHI.js./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-D7gUVql5.js:./public/vue-assets/assets/AskAnything-DgI0NfRA.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-BqQiLGFF.js./public/vue-assets/assets/deal-view-D4YlPwr_.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWAdERcJ.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-CyAPGoFk.js./public/vue-assets/assets/StatusBadge-DNHiCr2i.js./public/vue-assets/assets/kiosk-dfcpodo5.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-BVnPilVP.js../public/vue-assets/assets/ListView-DJD6SV4A.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js:./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-CsD0iLAi.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-B3B12M60.js:./public/vue-assets/assets/OrgSettingsLayout-DatDldIe.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D1gm80qQ.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js:./public/vue-assets/assets/team-insights-DRugjYCA.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-CxSmZv7h.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-Cp0YOK4U.js../public/vue-assets/assets/logged-in-layout-CE9ox17M.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 26.01s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
-5025856933011940221
|
NULL
|
click
|
ocr
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelplall= Support Daily - in 1 h 13 m100% <47APP (-zsh)X4-zshDOCKER• ₴1DEV (docker)• *2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-mxFxJiHI.js./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-D7gUVql5.js:./public/vue-assets/assets/AskAnything-DgI0NfRA.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-BqQiLGFF.js./public/vue-assets/assets/deal-view-D4YlPwr_.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWAdERcJ.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-CyAPGoFk.js./public/vue-assets/assets/StatusBadge-DNHiCr2i.js./public/vue-assets/assets/kiosk-dfcpodo5.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-BVnPilVP.js../public/vue-assets/assets/ListView-DJD6SV4A.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js:./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-CsD0iLAi.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-B3B12M60.js:./public/vue-assets/assets/OrgSettingsLayout-DatDldIe.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D1gm80qQ.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js:./public/vue-assets/assets/team-insights-DRugjYCA.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-CxSmZv7h.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-Cp0YOK4U.js../public/vue-assets/assets/logged-in-layout-CE9ox17M.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 26.01s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
|
46774
|
985
|
0
|
2026-04-17T10:47:44.697325+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422864697_m1.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelplall= Support Daily - in 1 h 13 m100% <47APP (-zsh)X4-zshDOCKER• ₴1DEV (docker)• *2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-mxFxJiHI.js./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-D7gUVql5.js:./public/vue-assets/assets/AskAnything-DgI0NfRA.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-BqQiLGFF.js./public/vue-assets/assets/deal-view-D4YlPwr_.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWAdERcJ.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-CyAPGoFk.js./public/vue-assets/assets/StatusBadge-DNHiCr2i.js./public/vue-assets/assets/kiosk-dfcpodo5.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-BVnPilVP.js../public/vue-assets/assets/ListView-DJD6SV4A.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js:./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-CsD0iLAi.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-B3B12M60.js:./public/vue-assets/assets/OrgSettingsLayout-DatDldIe.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D1gm80qQ.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js:./public/vue-assets/assets/team-insights-DRugjYCA.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-CxSmZv7h.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-Cp0YOK4U.js../public/vue-assets/assets/logged-in-layout-CE9ox17M.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 26.01s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
8300062941550214018
|
NULL
|
click
|
ocr
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelplall= Support Daily - in 1 h 13 m100% <47APP (-zsh)X4-zshDOCKER• ₴1DEV (docker)• *2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-mxFxJiHI.js./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-D7gUVql5.js:./public/vue-assets/assets/AskAnything-DgI0NfRA.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-BqQiLGFF.js./public/vue-assets/assets/deal-view-D4YlPwr_.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWAdERcJ.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-CyAPGoFk.js./public/vue-assets/assets/StatusBadge-DNHiCr2i.js./public/vue-assets/assets/kiosk-dfcpodo5.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-BVnPilVP.js../public/vue-assets/assets/ListView-DJD6SV4A.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js:./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-CsD0iLAi.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-B3B12M60.js:./public/vue-assets/assets/OrgSettingsLayout-DatDldIe.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D1gm80qQ.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js:./public/vue-assets/assets/team-insights-DRugjYCA.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-CxSmZv7h.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-Cp0YOK4U.js../public/vue-assets/assets/logged-in-layout-CE9ox17M.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 26.01s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
46773
|
|
46775
|
986
|
0
|
2026-04-17T10:47:44.697411+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776422864697_m2.jpg...
|
PhpStorm
|
faVsco.js – SF [jiminny@localhost]
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY].php-cs-fixer.dist.phpphp.phpstorm.meta.php=.phpunit.result.cacheE.prettierignoreE windsurfrulespip _lde_nelper.pnppnpce neloermoces.onepnp aruisani composer.isonO composer.lockdependency-checker.jsonO dev.jsonE ids.txt=infection.json.distM-INSALL.mdM+ INTERNAL WEBHOOK SETUPjiminny_storageM+ licenses.mdM MakefileOpackage-lock.json= phpstan.neon.dist= phpstan-baseline.neon< phpunit.xmlTa raw_sqLquery.sqlM+ README.mdsonar-project.properties= test.py<> Untitled Diagram.xmlIs vetur.config.jsM-+ WEbnOOK HILIEKING_IMPLE› Iib External Librariesv E® Scratches and Consolesv D Database Consoles© AutomatedReportsService.php© SendReportJob.phpC ReportController.phplokenbullaer.onoc leamsetuocontroller.onp• Filesystem.php© Team.php© RequestGenerateReportJob.phpT InteractsWithPivotTable.phg© CreateHeldActivityEvent.phpOpportunitySyncTrait.phpC OpportunityUpdated.php© SendReportMailJob.phpphp api.php© TrackProviderInstalledEvent.phpC Opportunity.phpC OpportunityStageUpdated.phpc) FventService?rovider.onm© RunOpportunityAiAnalysis.php( ImportBatchJobTrait.php© OpportunityPendingAiAnalysisAfterStageChanged.php© ProcessAiAutomationAnalysisResults.php(C) Service.php© ImportOpportunityBatch.php101819281030cachedStagesCcW165trait OpportunitySyncTraitA33 X2 X19 A Y 166private function resolveForecastCategory(?string $forecastCategory): stringf...1672 usages=169private function importExternalFieldData(array $properties, int $opportunitylra, 170171$crmFields = $this->getOpportunitySyncableFieldsO;=172$this->import0pportunityCrmFieldData(Sproperties, $crmFields, Sopportunityi17310331034103510481049105010511052Lusaeesprivate function importOpportunityContacts(Opportunity Sopportunity, array $as:177/*** Sync opportunity contacts using differential approach* This compares current vs new associations and only makes necessary changes=175176=1791801811821 usageprivate function syncOpportunityContactsDifferential(Opportunity $opportunity,1070private function getcurrentContactCrmIds(Opportunity $opportunity): array{..., 187A console [EU]4 DEAL RISKS [EU]A DI [EU]dEuleUv& jiminny@localhost& console yiminny @localr4 DI liiminnv@localhosti4 HS_local [jiminny@localA SF [jiminny@localhost]A zoho_dev [jiminny@loceY A PRODД0/110771078107910801 usageprivate function logContactAssociationChanges(Opportunity Sopportunity,array $currentContactCrmIds,array $contactAssociations,array $contactsToAdd,array +concacustokemove): void {...}100-189190191192—193services+,o,cv D DatabasevdtuA console 1 s 59 msuni crm conticurations "s 39msdjiminny@localhost4SF4 HS_localV A PROD4 console 1 s 806 msV A STAGING& consoleOutputiD # 1695 X3 rows+=S0T2 ICIsImtpzC16l7VmNwrhzGrKLT0wZDKtNDLKNy04ZWI2LTAZNmNLM...FQG0A• expires Y177633617617296136151776509176I refresh_token_expires T3 rows retrieved staruino trom 1in 353 ms (execution: 14 ms, Tetching: 3/g ms= custom.logE laravel.logA SF jiminny@localhost] XC scratch_1json< Hs local liminnyalocalnostA console (EU]© CrmEntityRepository.phpA console [PROD]A console [STAGING]XAutovPlaygroundSELECT * FROM automated_reports order by za desc;SELECT * FROMautomated_report_results order by id desc;select * from activity_searches where user_id = 143;select * from ask_anything_prompts;V connect.vuefi crm_configurations (EU]V Onboard.vueMa liminnv vM09412 X2 X4AVSELECT * FROM groups WHERE id = 1439;SELECT * FROM users WHERE group_id = 1439;select * from permissions; # 158select * from roles;select * from permission_role.select * from teams where id = 1;select * from groups g JOIN playbooks p 1..n<->1: on g.playbook_id = p.id where g.team_id = 1;select * from groups where id = 28;select * from playbooks where team_id = 1;select * from playbooks where id = 179;select * from playbook_categories where id = 1391;select * from users where id = 143;select * from crm_profiles where user_id = 143;select * from activities where crm_configuration_id = 39 and type = 'conference'and crm_provider_id IS NOT NULL ORDER by id desc;select * from activities where id = 422003; # 00U0400000pB6FpMACSELECT ar.ig, ar.wuig, ar.mediantxpe, ar.status, a.txReFROM automated_report_results arJOIN automated_reports a ON a.id = ar.repontaidWHERE a.txpe = 'ask_jiminnx"LIMIT 10;select * from teams where id = 3143;select * from crm_configurations where id = 500;select * from users where name = 'Integration Account'; # 1695SELECT * FROM social_accounts WHERE sociable_id = 1695;lablf Support Daily • in 1h 13 mAAutomatedRenortsCommandTest100% 145Fri 17 Apr 13:47:44CascadeAutomated Report RetrDebugging OpportunitUpdate Connection Loconnect.vue tront-end/src/components/connecnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your (IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check:1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? — you may be running a stale build that doesn't include your changesSearched.intecrationAoo@nClickin tront-enc/src/cents/connect/connect.vue (2)The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44• connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [Integratlonado incecrac1onApouncllck called arter cllckine tne outton, tne dev server nasn't olckea up tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).wAsk anything (284L)+ <> Code Claude Sonnet 4.6.O provider Yu cooqle<null> zoom-phone<null> integration-app! state Ytuul-retreshfyll-refreshconnectedauth_scope Yopenia nutps://www.googleap1s.com/auch/user1nro.prorzle nctps://www.googleap1s.com/auch/calendar nutp..phone:read:admin user:read:admin<null>• :-CSV vДOB,retry_after Y00 cr2020<nul><null>20242026-W Windsurf Teams 193:1 0 UTF-84 spaces...
|
NULL
|
-2590056953431532604
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorFV PhpStormFileEditViewNavigateCodeLaravelRefactorFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY].php-cs-fixer.dist.phpphp.phpstorm.meta.php=.phpunit.result.cacheE.prettierignoreE windsurfrulespip _lde_nelper.pnppnpce neloermoces.onepnp aruisani composer.isonO composer.lockdependency-checker.jsonO dev.jsonE ids.txt=infection.json.distM-INSALL.mdM+ INTERNAL WEBHOOK SETUPjiminny_storageM+ licenses.mdM MakefileOpackage-lock.json= phpstan.neon.dist= phpstan-baseline.neon< phpunit.xmlTa raw_sqLquery.sqlM+ README.mdsonar-project.properties= test.py<> Untitled Diagram.xmlIs vetur.config.jsM-+ WEbnOOK HILIEKING_IMPLE› Iib External Librariesv E® Scratches and Consolesv D Database Consoles© AutomatedReportsService.php© SendReportJob.phpC ReportController.phplokenbullaer.onoc leamsetuocontroller.onp• Filesystem.php© Team.php© RequestGenerateReportJob.phpT InteractsWithPivotTable.phg© CreateHeldActivityEvent.phpOpportunitySyncTrait.phpC OpportunityUpdated.php© SendReportMailJob.phpphp api.php© TrackProviderInstalledEvent.phpC Opportunity.phpC OpportunityStageUpdated.phpc) FventService?rovider.onm© RunOpportunityAiAnalysis.php( ImportBatchJobTrait.php© OpportunityPendingAiAnalysisAfterStageChanged.php© ProcessAiAutomationAnalysisResults.php(C) Service.php© ImportOpportunityBatch.php101819281030cachedStagesCcW165trait OpportunitySyncTraitA33 X2 X19 A Y 166private function resolveForecastCategory(?string $forecastCategory): stringf...1672 usages=169private function importExternalFieldData(array $properties, int $opportunitylra, 170171$crmFields = $this->getOpportunitySyncableFieldsO;=172$this->import0pportunityCrmFieldData(Sproperties, $crmFields, Sopportunityi17310331034103510481049105010511052Lusaeesprivate function importOpportunityContacts(Opportunity Sopportunity, array $as:177/*** Sync opportunity contacts using differential approach* This compares current vs new associations and only makes necessary changes=175176=1791801811821 usageprivate function syncOpportunityContactsDifferential(Opportunity $opportunity,1070private function getcurrentContactCrmIds(Opportunity $opportunity): array{..., 187A console [EU]4 DEAL RISKS [EU]A DI [EU]dEuleUv& jiminny@localhost& console yiminny @localr4 DI liiminnv@localhosti4 HS_local [jiminny@localA SF [jiminny@localhost]A zoho_dev [jiminny@loceY A PRODД0/110771078107910801 usageprivate function logContactAssociationChanges(Opportunity Sopportunity,array $currentContactCrmIds,array $contactAssociations,array $contactsToAdd,array +concacustokemove): void {...}100-189190191192—193services+,o,cv D DatabasevdtuA console 1 s 59 msuni crm conticurations "s 39msdjiminny@localhost4SF4 HS_localV A PROD4 console 1 s 806 msV A STAGING& consoleOutputiD # 1695 X3 rows+=S0T2 ICIsImtpzC16l7VmNwrhzGrKLT0wZDKtNDLKNy04ZWI2LTAZNmNLM...FQG0A• expires Y177633617617296136151776509176I refresh_token_expires T3 rows retrieved staruino trom 1in 353 ms (execution: 14 ms, Tetching: 3/g ms= custom.logE laravel.logA SF jiminny@localhost] XC scratch_1json< Hs local liminnyalocalnostA console (EU]© CrmEntityRepository.phpA console [PROD]A console [STAGING]XAutovPlaygroundSELECT * FROM automated_reports order by za desc;SELECT * FROMautomated_report_results order by id desc;select * from activity_searches where user_id = 143;select * from ask_anything_prompts;V connect.vuefi crm_configurations (EU]V Onboard.vueMa liminnv vM09412 X2 X4AVSELECT * FROM groups WHERE id = 1439;SELECT * FROM users WHERE group_id = 1439;select * from permissions; # 158select * from roles;select * from permission_role.select * from teams where id = 1;select * from groups g JOIN playbooks p 1..n<->1: on g.playbook_id = p.id where g.team_id = 1;select * from groups where id = 28;select * from playbooks where team_id = 1;select * from playbooks where id = 179;select * from playbook_categories where id = 1391;select * from users where id = 143;select * from crm_profiles where user_id = 143;select * from activities where crm_configuration_id = 39 and type = 'conference'and crm_provider_id IS NOT NULL ORDER by id desc;select * from activities where id = 422003; # 00U0400000pB6FpMACSELECT ar.ig, ar.wuig, ar.mediantxpe, ar.status, a.txReFROM automated_report_results arJOIN automated_reports a ON a.id = ar.repontaidWHERE a.txpe = 'ask_jiminnx"LIMIT 10;select * from teams where id = 3143;select * from crm_configurations where id = 500;select * from users where name = 'Integration Account'; # 1695SELECT * FROM social_accounts WHERE sociable_id = 1695;lablf Support Daily • in 1h 13 mAAutomatedRenortsCommandTest100% 145Fri 17 Apr 13:47:44CascadeAutomated Report RetrDebugging OpportunitUpdate Connection Loconnect.vue tront-end/src/components/connecnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your (IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check:1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? — you may be running a stale build that doesn't include your changesSearched.intecrationAoo@nClickin tront-enc/src/cents/connect/connect.vue (2)The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44• connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [Integratlonado incecrac1onApouncllck called arter cllckine tne outton, tne dev server nasn't olckea up tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).wAsk anything (284L)+ <> Code Claude Sonnet 4.6.O provider Yu cooqle<null> zoom-phone<null> integration-app! state Ytuul-retreshfyll-refreshconnectedauth_scope Yopenia nutps://www.googleap1s.com/auch/user1nro.prorzle nctps://www.googleap1s.com/auch/calendar nutp..phone:read:admin user:read:admin<null>• :-CSV vДOB,retry_after Y00 cr2020<nul><null>20242026-W Windsurf Teams 193:1 0 UTF-84 spaces...
|
NULL
|
|
46925
|
NULL
|
0
|
2026-04-17T10:52:12.907193+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423132907_m1.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/dashboard
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-4465696449359315208
|
-2648858699392996788
|
click
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)...
|
NULL
|
|
46933
|
NULL
|
0
|
2026-04-17T10:52:44.201703+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423164201_m2.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/dashboard
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
WORK, Google Account: [EMAIL]
Main menu
New chat
Gemini
PRO
PRO
Conversation with Gemini
Conversation with Gemini
Copy prompt
Edit
You said firefox how to preseve console
You said
firefox how to preseve console
Show more options
Enter a prompt for Gemini
encrypted
Enter a prompt for Gemini
encrypted
Open upload file menu
Tools
Open mode picker
Pro
Stop response
Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.
Your privacy & Gemini Opens in a new window
Your privacy & Gemini
Opens in a new window
Gemini is typing
Summarize page
Summarize page
install
My Recordings
My Recordings
Everyone's Recordings
Everyone's Recordings
No Recordings
Schedule
Schedule
Invite Notetaker
This Week
This Week
My Schedule
My Schedule
No Meetings
Trending this month
Trending this month
Sort by Most played
Sort by
Most played
No Recordings
Live Feed
Live Feed
No Activity
Clear the Web Console output (⌘K, Ctrl+L)
Filter Output
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Show/hide message details.
GET
[URL_WITH_CREDENTIALS]
[URL_WITH_CREDENTIALS]
[HTTP/2
200
OK 0ms]
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard
dashboard
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAXC-qNiXg7Q.woff2
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAXC-qNiXg7Q.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard
dashboard
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_FQftx9897sxZ.woff2
https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_FQftx9897sxZ.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard
dashboard
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2
https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.31666666,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.3402778,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":7,"bounds":{"left":0.2171875,"top":0.047916666,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":7,"bounds":{"left":0.23125,"top":0.047916666,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"WORK, Google Account: lukas.kovalik@jiminny.com","depth":12,"bounds":{"left":0.228125,"top":0.090277776,"width":0.015625,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Main menu","depth":12,"bounds":{"left":0.0984375,"top":0.090277776,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New chat","depth":12,"bounds":{"left":0.1140625,"top":0.09097222,"width":0.03359375,"height":0.02638889},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":15,"bounds":{"left":0.1171875,"top":0.09513889,"width":0.02578125,"height":0.018055556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"PRO","depth":11,"bounds":{"left":0.20820312,"top":0.09583333,"width":0.017578125,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"PRO","depth":13,"bounds":{"left":0.21132812,"top":0.09791667,"width":0.011328125,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Conversation with Gemini","depth":15,"bounds":{"left":0.09335937,"top":0.12847222,"width":0.000390625,"height":0.00069444446},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":16,"bounds":{"left":0.09335937,"top":0.13055556,"width":0.14101562,"height":0.022222223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy prompt","depth":20,"bounds":{"left":0.1203125,"top":0.15972222,"width":0.015625,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Edit","depth":20,"bounds":{"left":0.1375,"top":0.15972222,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"You said firefox how to preseve console","depth":20,"bounds":{"left":0.1609375,"top":0.16805555,"width":0.072265625,"height":0.03888889},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":22,"bounds":{"left":0.09335937,"top":0.1701389,"width":0.0234375,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"firefox how to preseve console","depth":22,"bounds":{"left":0.1609375,"top":0.17083333,"width":0.06289063,"height":0.034027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show more options","depth":18,"bounds":{"left":0.22382812,"top":0.23194444,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXTextArea","text":"Enter a prompt for Gemini\nencrypted","depth":20,"bounds":{"left":0.109375,"top":0.8354167,"width":0.125,"height":0.016666668},"value":"Enter a prompt for Gemini\nencrypted","help_text":"","role_description":"text entry area","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXStaticText","text":"Enter a prompt for Gemini","depth":21,"bounds":{"left":0.1171875,"top":0.8354167,"width":0.08203125,"height":0.016666668},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"encrypted","depth":21,"bounds":{"left":0.10820313,"top":0.8354167,"width":0.0078125,"height":0.016666668},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open upload file menu","depth":20,"bounds":{"left":0.1046875,"top":0.86527777,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tools","depth":18,"bounds":{"left":0.1234375,"top":0.86527777,"width":0.015625,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open mode picker","depth":20,"bounds":{"left":0.190625,"top":0.8645833,"width":0.03046875,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pro","depth":23,"bounds":{"left":0.196875,"top":0.87222224,"width":0.00859375,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Stop response","depth":19,"bounds":{"left":0.22265625,"top":0.86388886,"width":0.01640625,"height":0.029166667},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.","depth":17,"bounds":{"left":0.10039063,"top":0.9097222,"width":0.14296874,"height":0.022222223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Your privacy & Gemini Opens in a new window","depth":17,"bounds":{"left":0.1484375,"top":0.93194443,"width":0.046875,"height":0.011111111},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Your privacy & Gemini","depth":18,"bounds":{"left":0.1484375,"top":0.93194443,"width":0.046875,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Opens in a new window","depth":19,"bounds":{"left":0.09335937,"top":0.93125,"width":0.05078125,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini is typing","depth":9,"bounds":{"left":0.09335937,"top":0.07986111,"width":0.0421875,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Summarize page","depth":7,"bounds":{"left":0.1,"top":0.96319443,"width":0.06289063,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Summarize page","depth":9,"bounds":{"left":0.10664062,"top":0.9673611,"width":0.049609374,"height":0.013888889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"install","depth":11,"bounds":{"left":0.23125,"top":0.9451389,"width":0.01875,"height":0.030555556},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"My Recordings","depth":10,"bounds":{"left":0.25703126,"top":0.10277778,"width":0.043359376,"height":0.045833334},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"My Recordings","depth":11,"bounds":{"left":0.2609375,"top":0.12013889,"width":0.035546876,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Everyone's Recordings","depth":10,"bounds":{"left":0.39648438,"top":0.10277778,"width":0.061328124,"height":0.045833334},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Everyone's Recordings","depth":11,"bounds":{"left":0.40039062,"top":0.12013889,"width":0.053515624,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Recordings","depth":13,"bounds":{"left":0.33945313,"top":0.23125,"width":0.0359375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Schedule","depth":9,"bounds":{"left":0.2589844,"top":0.2888889,"width":0.028515626,"height":0.023611112},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Schedule","depth":10,"bounds":{"left":0.2589844,"top":0.29305556,"width":0.028515626,"height":0.015277778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Invite Notetaker","depth":10,"bounds":{"left":0.40976563,"top":0.28680557,"width":0.051953126,"height":0.025},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXComboBox","text":"This Week","depth":10,"bounds":{"left":0.2589844,"top":0.3298611,"width":0.196875,"height":0.025694445},"value":"This Week","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"This Week","depth":12,"bounds":{"left":0.26328126,"top":0.33680555,"width":0.02578125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"My Schedule","depth":10,"bounds":{"left":0.2589844,"top":0.3625,"width":0.196875,"height":0.025694445},"value":"My Schedule","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"My Schedule","depth":12,"bounds":{"left":0.26328126,"top":0.36944443,"width":0.03125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Meetings","depth":12,"bounds":{"left":0.34179688,"top":0.48055556,"width":0.03125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Trending this month","depth":9,"bounds":{"left":0.26289064,"top":0.56319445,"width":0.054296874,"height":0.016666668},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Trending this month","depth":10,"bounds":{"left":0.26289064,"top":0.56458336,"width":0.054296874,"height":0.013888889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Sort by Most played","depth":9,"bounds":{"left":0.3921875,"top":0.55833334,"width":0.059765626,"height":0.025694445},"value":"Sort by Most played","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Sort by","depth":10,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Most played","depth":11,"bounds":{"left":0.39648438,"top":0.56527776,"width":0.0296875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Recordings","depth":12,"bounds":{"left":0.33945313,"top":0.68333334,"width":0.0359375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Live Feed","depth":9,"bounds":{"left":0.26289064,"top":0.7590278,"width":0.02578125,"height":0.016666668},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Live Feed","depth":10,"bounds":{"left":0.26289064,"top":0.7604167,"width":0.02578125,"height":0.013888889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Activity","depth":12,"bounds":{"left":0.34375,"top":0.87222224,"width":0.02734375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Clear the Web Console output (⌘K, Ctrl+L)","depth":15,"bounds":{"left":0.46328124,"top":0.068055555,"width":0.01015625,"height":0.013888889},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXTextField","text":"Filter Output","depth":15,"bounds":{"left":0.47578126,"top":0.065972224,"width":0.36132812,"height":0.018055556},"role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Errors","depth":15,"bounds":{"left":0.8417969,"top":0.068055555,"width":0.0171875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Warnings","depth":15,"bounds":{"left":0.85976565,"top":0.068055555,"width":0.023828125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Info","depth":15,"bounds":{"left":0.884375,"top":0.068055555,"width":0.0125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Logs","depth":15,"bounds":{"left":0.89765626,"top":0.068055555,"width":0.014453125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Debug","depth":15,"bounds":{"left":0.9128906,"top":0.068055555,"width":0.01796875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"CSS","depth":15,"bounds":{"left":0.9359375,"top":0.068055555,"width":0.01328125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"XHR","depth":15,"bounds":{"left":0.95,"top":0.068055555,"width":0.013671875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Requests","depth":15,"bounds":{"left":0.9644531,"top":0.068055555,"width":0.023828125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Console Settings","depth":15,"bounds":{"left":0.9898437,"top":0.06527778,"width":0.01015625,"height":0.019444445},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.08680555,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.0875,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/dashboard","depth":20,"bounds":{"left":0.484375,"top":0.0875,"width":0.4519531,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/dashboard","depth":21,"bounds":{"left":0.484375,"top":0.0875,"width":0.095703125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/1.1","depth":21,"bounds":{"left":0.9386719,"top":0.0875,"width":0.02578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9652344,"top":0.0875,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.97382814,"top":0.0875,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.4703125,"top":0.10138889,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Content-Security-Policy warnings","depth":20,"bounds":{"left":0.4765625,"top":0.10208333,"width":0.0828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"2","depth":21,"bounds":{"left":0.5660156,"top":0.103472225,"width":0.00234375,"height":0.007638889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.11597222,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.11666667,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Roboto:wght@500&display=swap","depth":20,"bounds":{"left":0.484375,"top":0.11666667,"width":0.4519531,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Roboto:wght@500&display=swap","depth":21,"bounds":{"left":0.484375,"top":0.11666667,"width":0.29726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/2","depth":21,"bounds":{"left":0.9386719,"top":0.11666667,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.96015626,"top":0.11666667,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OK 0ms]","depth":21,"bounds":{"left":0.96875,"top":0.11666667,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at","depth":21,"bounds":{"left":0.471875,"top":0.13125,"width":0.30507812,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2","depth":21,"bounds":{"left":0.7769531,"top":0.13125,"width":0.18359375,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2","depth":22,"bounds":{"left":0.7769531,"top":0.13125,"width":0.18359375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"because it violates the following directive: “font-src 'self'","depth":21,"bounds":{"left":0.471875,"top":0.13125,"width":0.4910156,"height":0.019444445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com","depth":21,"bounds":{"left":0.63203126,"top":0.14097223,"width":0.06992187,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com","depth":22,"bounds":{"left":0.63203126,"top":0.14097223,"width":0.06992187,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/","depth":21,"bounds":{"left":0.7042969,"top":0.14097223,"width":0.07265625,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/","depth":22,"bounds":{"left":0.7042969,"top":0.14097223,"width":0.07265625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://js.intercomcdn.com","depth":21,"bounds":{"left":0.7792969,"top":0.14097223,"width":0.0671875,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://js.intercomcdn.com","depth":22,"bounds":{"left":0.7792969,"top":0.14097223,"width":0.0671875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"”","depth":21,"bounds":{"left":0.84648436,"top":0.14097223,"width":0.002734375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"dashboard","depth":20,"bounds":{"left":0.96601564,"top":0.13125,"width":0.0234375,"height":0.009722223},"help_text":"View source in Debugger → https://app.dev.jiminny.com/dashboard","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"dashboard","depth":22,"bounds":{"left":0.96601564,"top":0.13125,"width":0.0234375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at","depth":21,"bounds":{"left":0.471875,"top":0.15555556,"width":0.30507812,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAXC-qNiXg7Q.woff2","depth":21,"bounds":{"left":0.7769531,"top":0.15555556,"width":0.178125,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAXC-qNiXg7Q.woff2","depth":22,"bounds":{"left":0.7769531,"top":0.15555556,"width":0.178125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"because it violates the following directive: “font-src 'self'","depth":21,"bounds":{"left":0.471875,"top":0.15555556,"width":0.4859375,"height":0.019444445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com","depth":21,"bounds":{"left":0.63203126,"top":0.16527778,"width":0.06992187,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com","depth":22,"bounds":{"left":0.63203126,"top":0.16527778,"width":0.06992187,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/","depth":21,"bounds":{"left":0.7042969,"top":0.16527778,"width":0.07265625,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/","depth":22,"bounds":{"left":0.7042969,"top":0.16527778,"width":0.07265625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://js.intercomcdn.com","depth":21,"bounds":{"left":0.7792969,"top":0.16527778,"width":0.0671875,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://js.intercomcdn.com","depth":22,"bounds":{"left":0.7792969,"top":0.16527778,"width":0.0671875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"”","depth":21,"bounds":{"left":0.84648436,"top":0.16527778,"width":0.002734375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"dashboard","depth":20,"bounds":{"left":0.96601564,"top":0.15555556,"width":0.0234375,"height":0.009722223},"help_text":"View source in Debugger → https://app.dev.jiminny.com/dashboard","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"dashboard","depth":22,"bounds":{"left":0.96601564,"top":0.15555556,"width":0.0234375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at","depth":21,"bounds":{"left":0.471875,"top":0.17986111,"width":0.30507812,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_FQftx9897sxZ.woff2","depth":21,"bounds":{"left":0.471875,"top":0.17986111,"width":0.4910156,"height":0.019444445},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_FQftx9897sxZ.woff2","depth":22,"bounds":{"left":0.471875,"top":0.17986111,"width":0.4910156,"height":0.019444445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"because it violates the following directive: “font-src 'self'","depth":21,"bounds":{"left":0.4796875,"top":0.18958333,"width":0.16289063,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com","depth":21,"bounds":{"left":0.6425781,"top":0.18958333,"width":0.06953125,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com","depth":22,"bounds":{"left":0.6425781,"top":0.18958333,"width":0.06953125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/","depth":21,"bounds":{"left":0.71484375,"top":0.18958333,"width":0.072265625,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/","depth":22,"bounds":{"left":0.71484375,"top":0.18958333,"width":0.072265625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://js.intercomcdn.com","depth":21,"bounds":{"left":0.78984374,"top":0.18958333,"width":0.0671875,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://js.intercomcdn.com","depth":22,"bounds":{"left":0.78984374,"top":0.18958333,"width":0.0671875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"”","depth":21,"bounds":{"left":0.8570312,"top":0.18958333,"width":0.00234375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"dashboard","depth":20,"bounds":{"left":0.96601564,"top":0.17986111,"width":0.0234375,"height":0.009722223},"help_text":"View source in Debugger → https://app.dev.jiminny.com/dashboard","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"dashboard","depth":22,"bounds":{"left":0.96601564,"top":0.17986111,"width":0.0234375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at","depth":21,"bounds":{"left":0.471875,"top":0.20416667,"width":0.30507812,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2","depth":21,"bounds":{"left":0.471875,"top":0.20416667,"width":0.4910156,"height":0.019444445},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2","depth":22,"bounds":{"left":0.471875,"top":0.20416667,"width":0.4910156,"height":0.019444445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"because it violates the following directive: “font-src 'self'","depth":21,"bounds":{"left":0.47460938,"top":0.21388888,"width":0.1625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com","depth":21,"bounds":{"left":0.6371094,"top":0.21388888,"width":0.06992187,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com","depth":22,"bounds":{"left":0.6371094,"top":0.21388888,"width":0.06992187,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/","depth":21,"bounds":{"left":0.7097656,"top":0.21388888,"width":0.072265625,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/","depth":22,"bounds":{"left":0.7097656,"top":0.21388888,"width":0.072265625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://js.intercomcdn.com","depth":21,"bounds":{"left":0.7847656,"top":0.21388888,"width":0.0671875,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://js.intercomcdn.com","depth":22,"bounds":{"left":0.7847656,"top":0.21388888,"width":0.0671875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"”","depth":21,"bounds":{"left":0.85195315,"top":0.21388888,"width":0.00234375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"dashboard","depth":20,"bounds":{"left":0.96601564,"top":0.20416667,"width":0.0234375,"height":0.009722223},"help_text":"View source in Debugger → https://app.dev.jiminny.com/dashboard","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-3520186457033888925
|
4293020297422048420
|
visual_change
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
WORK, Google Account: [EMAIL]
Main menu
New chat
Gemini
PRO
PRO
Conversation with Gemini
Conversation with Gemini
Copy prompt
Edit
You said firefox how to preseve console
You said
firefox how to preseve console
Show more options
Enter a prompt for Gemini
encrypted
Enter a prompt for Gemini
encrypted
Open upload file menu
Tools
Open mode picker
Pro
Stop response
Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.
Your privacy & Gemini Opens in a new window
Your privacy & Gemini
Opens in a new window
Gemini is typing
Summarize page
Summarize page
install
My Recordings
My Recordings
Everyone's Recordings
Everyone's Recordings
No Recordings
Schedule
Schedule
Invite Notetaker
This Week
This Week
My Schedule
My Schedule
No Meetings
Trending this month
Trending this month
Sort by Most played
Sort by
Most played
No Recordings
Live Feed
Live Feed
No Activity
Clear the Web Console output (⌘K, Ctrl+L)
Filter Output
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Show/hide message details.
GET
[URL_WITH_CREDENTIALS]
[URL_WITH_CREDENTIALS]
[HTTP/2
200
OK 0ms]
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard
dashboard
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAXC-qNiXg7Q.woff2
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAXC-qNiXg7Q.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard
dashboard
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_FQftx9897sxZ.woff2
https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_FQftx9897sxZ.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard
dashboard
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2
https://fonts.gstatic.com/s/lato/v25/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard...
|
46932
|
|
46934
|
987
|
0
|
2026-04-17T10:53:02.563572+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423182563_m1.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/dashboard
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
WORK, Google Account: [EMAIL]
Main menu
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
Copy prompt
Edit
You said firefox how to preseve console
You said
firefox how to preseve console
Listen
Show more options
Show thinking
Gemini said
Gemini said
To preserve your console logs in Firefox so they don't clear when you refresh or navigate to a new page, you need to enable the
Persist Logs
setting.
Here are the two easiest ways to do it:
Method 1: Directly from the Console Tab (Quickest)
Method 1: Directly from the Console Tab (Quickest)
Open the Developer Tools by pressing
F12
(or
Ctrl
+
Shift
+
I
on Windows/Linux,
Cmd
+
Option
+
I
on Mac).
Click on the
Console
tab.
Look at the top right corner of the Console pane and click the
Gear icon
(Console settings).
In the dropdown menu, check the box next to
Persist Logs
.
Method 2: From the DevTools Settings
Method 2: From the DevTools Settings
Open the Developer Tools (
F12
).
Open the Settings menu by pressing
F1
while the DevTools window is focused (or click the three dots
...
in the top right of the DevTools panel and select
Settings
).
Scroll down to the
Common Preferences
section.
Check the box that says
Enable persistent logs
.
Once this is turned on, your console history and network logs will remain visible across page reloads and navigation until you manually clear them by clicking the trash can icon.
Enter a prompt for Gemini
encrypted
Enter a prompt for Gemini
encrypted
Open upload file menu
Tools
Open mode picker
Pro
Microphone
Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.
Your privacy & Gemini Opens in a new window
Your privacy & Gemini
Opens in a new window
Summarize page
Summarize page
install
My Recordings
My Recordings
Everyone's Recordings
Everyone's Recordings
No Recordings
Schedule
Schedule
Invite Notetaker
This Week
This Week
My Schedule
My Schedule
No Meetings
Trending this month
Trending this month
Sort by Most played
Sort by
Most played
No Recordings
Live Feed
Live Feed
No Activity
Clear the Web Console output (⌘K, Ctrl+L)
Filter Output
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Show/hide message details.
GET
[URL_WITH_CREDENTIALS]
[URL_WITH_CREDENTIALS]
[HTTP/2
200
OK 0ms]
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard
dashboard...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":7,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":7,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"WORK, Google Account: lukas.kovalik@jiminny.com","depth":12,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Main menu","depth":12,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Chat","depth":12,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":12,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":15,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy prompt","depth":21,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Edit","depth":21,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"You said firefox how to preseve console","depth":21,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":23,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"firefox how to preseve console","depth":23,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Listen","depth":22,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Show more options","depth":20,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Show thinking","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Gemini said","depth":20,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"To preserve your console logs in Firefox so they don't clear when you refresh or navigate to a new page, you need to enable the","depth":24,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Persist Logs","depth":24,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setting.","depth":24,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here are the two easiest ways to do it:","depth":24,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Method 1: Directly from the Console Tab (Quickest)","depth":23,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Method 1: Directly from the Console Tab (Quickest)","depth":24,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open the Developer Tools by pressing","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"F12","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(or","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Ctrl","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"+","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Shift","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"+","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"on Windows/Linux,","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Cmd","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"+","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Option","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"+","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"on Mac).","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Click on the","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Console","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"tab.","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Look at the top right corner of the Console pane and click the","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gear icon","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(Console settings).","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"In the dropdown menu, check the box next to","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Persist Logs","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Method 2: From the DevTools Settings","depth":23,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Method 2: From the DevTools Settings","depth":24,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open the Developer Tools (","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"F12","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":").","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open the Settings menu by pressing","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"F1","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"while the DevTools window is focused (or click the three dots","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"...","depth":27,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"in the top right of the DevTools panel and select","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Settings","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":").","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Scroll down to the","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Common Preferences","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"section.","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Check the box that says","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Enable persistent logs","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":26,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Once this is turned on, your console history and network logs will remain visible across page reloads and navigation until you manually clear them by clicking the trash can icon.","depth":24,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXTextArea","text":"Enter a prompt for Gemini\nencrypted","depth":20,"value":"Enter a prompt for Gemini\nencrypted","help_text":"","role_description":"text entry area","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXStaticText","text":"Enter a prompt for Gemini","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"encrypted","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open upload file menu","depth":20,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tools","depth":18,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open mode picker","depth":20,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pro","depth":23,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXCheckBox","text":"Microphone","depth":19,"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Your privacy & Gemini Opens in a new window","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Your privacy & Gemini","depth":18,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Opens in a new window","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Summarize page","depth":7,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Summarize page","depth":9,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"install","depth":11,"bounds":{"left":0.0,"top":0.0,"width":0.033333335,"height":0.04888889},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"My Recordings","depth":10,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"My Recordings","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Everyone's Recordings","depth":10,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Everyone's Recordings","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Recordings","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Schedule","depth":9,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Schedule","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Invite Notetaker","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXComboBox","text":"This Week","depth":10,"value":"This Week","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"This Week","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"My Schedule","depth":10,"value":"My Schedule","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"My Schedule","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Meetings","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Trending this month","depth":9,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Trending this month","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Sort by Most played","depth":9,"value":"Sort by Most played","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Sort by","depth":10,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Most played","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Recordings","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Live Feed","depth":9,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Live Feed","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Activity","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Clear the Web Console output (⌘K, Ctrl+L)","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXTextField","text":"Filter Output","depth":15,"role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Errors","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Warnings","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Info","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Logs","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Debug","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"CSS","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"XHR","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Requests","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Console Settings","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show/hide message details.","depth":17,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/dashboard","depth":20,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/dashboard","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/1.1","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Content-Security-Policy warnings","depth":20,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"2","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Roboto:wght@500&display=swap","depth":20,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Roboto:wght@500&display=swap","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/2","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OK 0ms]","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2","depth":21,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"because it violates the following directive: “font-src 'self'","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com","depth":21,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/","depth":21,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://js.intercomcdn.com","depth":21,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://js.intercomcdn.com","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"”","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"dashboard","depth":20,"help_text":"View source in Debugger → https://app.dev.jiminny.com/dashboard","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"dashboard","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
8704115142770106145
|
-432381689197282684
|
idle
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
WORK, Google Account: [EMAIL]
Main menu
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
Copy prompt
Edit
You said firefox how to preseve console
You said
firefox how to preseve console
Listen
Show more options
Show thinking
Gemini said
Gemini said
To preserve your console logs in Firefox so they don't clear when you refresh or navigate to a new page, you need to enable the
Persist Logs
setting.
Here are the two easiest ways to do it:
Method 1: Directly from the Console Tab (Quickest)
Method 1: Directly from the Console Tab (Quickest)
Open the Developer Tools by pressing
F12
(or
Ctrl
+
Shift
+
I
on Windows/Linux,
Cmd
+
Option
+
I
on Mac).
Click on the
Console
tab.
Look at the top right corner of the Console pane and click the
Gear icon
(Console settings).
In the dropdown menu, check the box next to
Persist Logs
.
Method 2: From the DevTools Settings
Method 2: From the DevTools Settings
Open the Developer Tools (
F12
).
Open the Settings menu by pressing
F1
while the DevTools window is focused (or click the three dots
...
in the top right of the DevTools panel and select
Settings
).
Scroll down to the
Common Preferences
section.
Check the box that says
Enable persistent logs
.
Once this is turned on, your console history and network logs will remain visible across page reloads and navigation until you manually clear them by clicking the trash can icon.
Enter a prompt for Gemini
encrypted
Enter a prompt for Gemini
encrypted
Open upload file menu
Tools
Open mode picker
Pro
Microphone
Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.
Your privacy & Gemini Opens in a new window
Your privacy & Gemini
Opens in a new window
Summarize page
Summarize page
install
My Recordings
My Recordings
Everyone's Recordings
Everyone's Recordings
No Recordings
Schedule
Schedule
Invite Notetaker
This Week
This Week
My Schedule
My Schedule
No Meetings
Trending this month
Trending this month
Sort by Most played
Sort by
Most played
No Recordings
Live Feed
Live Feed
No Activity
Clear the Web Console output (⌘K, Ctrl+L)
Filter Output
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Show/hide message details.
GET
[URL_WITH_CREDENTIALS]
[URL_WITH_CREDENTIALS]
[HTTP/2
200
OK 0ms]
Content-Security-Policy: (Report-Only policy) The page’s settings would block the loading of a resource (font-src) at
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2
https://fonts.gstatic.com/s/lato/v25/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2
because it violates the following directive: “font-src 'self'
https://app.dev.jiminny.com
https://app.dev.jiminny.com
https://app.dev.jiminny.com/
https://app.dev.jiminny.com/
https://js.intercomcdn.com
https://js.intercomcdn.com
”
dashboard
dashboard...
|
46925
|
|
46935
|
988
|
0
|
2026-04-17T10:53:14.636876+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423194636_m2.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/dashboard
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
WORK, Google Account: [EMAIL]
Main menu
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
Copy prompt
Edit
You said firefox how to preseve console
You said
firefox how to preseve console
Listen
Show more options
Show thinking
Gemini said
Gemini said
To preserve your console logs in Firefox so they don't clear when you refresh or navigate to a new page, you need to enable the
Persist Logs
setting.
Here are the two easiest ways to do it:
Method 1: Directly from the Console Tab (Quickest)
Method 1: Directly from the Console Tab (Quickest)
Open the Developer Tools by pressing
F12
(or
Ctrl
+
Shift
+
I
on Windows/Linux,
Cmd
+
Option
+
I
on Mac).
Click on the
Console
tab.
Look at the top right corner of the Console pane and click the
Gear icon
(Console settings).
In the dropdown menu, check the box next to
Persist Logs
.
Method 2: From the DevTools Settings
Method 2: From the DevTools Settings
Open the Developer Tools (
F12
).
Open the Settings menu by pressing
F1
while the DevTools window is focused (or click the three dots
...
in the top right of the DevTools panel and select
Settings
).
Scroll down to the
Common Preferences
section.
Check the box that says
Enable persistent logs
.
Once this is turned on, your console history and network logs will remain visible across page reloads and navigation until you manually clear them by clicking the trash can icon.
Enter a prompt for Gemini
encrypted
Enter a prompt for Gemini
encrypted
Open upload file menu
Tools
Open mode picker
Pro
Microphone
Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.
Your privacy & Gemini Opens in a new window
Your privacy & Gemini
Opens in a new window
Summarize page
Summarize page
install
My Recordings
My Recordings
Everyone's Recordings
Everyone's Recordings
No Recordings
Schedule
Schedule
Invite Notetaker
This Week
This Week
My Schedule
My Schedule
No Meetings
Trending this month...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.31666666,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.3402778,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":7,"bounds":{"left":0.2171875,"top":0.047916666,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":7,"bounds":{"left":0.23125,"top":0.047916666,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"WORK, Google Account: lukas.kovalik@jiminny.com","depth":12,"bounds":{"left":0.228125,"top":0.090277776,"width":0.015625,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Main menu","depth":12,"bounds":{"left":0.0984375,"top":0.090277776,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Chat","depth":12,"bounds":{"left":0.1953125,"top":0.090277776,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":12,"bounds":{"left":0.2109375,"top":0.090277776,"width":0.015625,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":15,"bounds":{"left":0.09335937,"top":0.12847222,"width":0.000390625,"height":0.00069444446},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":16,"bounds":{"left":0.09335937,"top":0.13055556,"width":0.14101562,"height":0.022222223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy prompt","depth":21,"bounds":{"left":0.1203125,"top":0.15972222,"width":0.015625,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Edit","depth":21,"bounds":{"left":0.1375,"top":0.15972222,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"You said firefox how to preseve console","depth":21,"bounds":{"left":0.1609375,"top":0.16805555,"width":0.072265625,"height":0.03888889},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":23,"bounds":{"left":0.09335937,"top":0.1701389,"width":0.0234375,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"firefox how to preseve console","depth":23,"bounds":{"left":0.1609375,"top":0.17083333,"width":0.06289063,"height":0.034027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Listen","depth":22,"bounds":{"left":0.22382812,"top":0.23472223,"width":0.015625,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Show more options","depth":20,"bounds":{"left":0.22382812,"top":0.22986111,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Show thinking","depth":26,"bounds":{"left":0.11953125,"top":0.23680556,"width":0.036328126,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Gemini said","depth":20,"bounds":{"left":0.11679687,"top":0.27291667,"width":0.000390625,"height":0.00069444446},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":21,"bounds":{"left":0.11679687,"top":0.27430555,"width":0.048046876,"height":0.016666668},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"To preserve your console logs in Firefox so they don't clear when you refresh or navigate to a new page, you need to enable the","depth":24,"bounds":{"left":0.10390625,"top":0.28125,"width":0.13007812,"height":0.050694443},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Persist Logs","depth":24,"bounds":{"left":0.10390625,"top":0.31736112,"width":0.13242188,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setting.","depth":24,"bounds":{"left":0.11835937,"top":0.33541667,"width":0.023046875,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here are the two easiest ways to do it:","depth":24,"bounds":{"left":0.10390625,"top":0.36458334,"width":0.10820313,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Method 1: Directly from the Console Tab (Quickest)","depth":23,"bounds":{"left":0.10390625,"top":0.4,"width":0.13242188,"height":0.033333335},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Method 1: Directly from the Console Tab (Quickest)","depth":24,"bounds":{"left":0.10390625,"top":0.40138888,"width":0.123046875,"height":0.03125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open the Developer Tools by pressing","depth":26,"bounds":{"left":0.11796875,"top":0.4409722,"width":0.10898437,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"F12","depth":27,"bounds":{"left":0.1203125,"top":0.46041667,"width":0.009765625,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(or","depth":26,"bounds":{"left":0.13242188,"top":0.45902777,"width":0.011328125,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Ctrl","depth":27,"bounds":{"left":0.14609376,"top":0.46041667,"width":0.01328125,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"+","depth":26,"bounds":{"left":0.16171876,"top":0.45902777,"width":0.006640625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Shift","depth":27,"bounds":{"left":0.17070313,"top":0.46041667,"width":0.01640625,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"+","depth":26,"bounds":{"left":0.18945312,"top":0.45902777,"width":0.00703125,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I","depth":27,"bounds":{"left":0.19882813,"top":0.46041667,"width":0.003125,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"on Windows/Linux,","depth":26,"bounds":{"left":0.11796875,"top":0.45902777,"width":0.09648438,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Cmd","depth":27,"bounds":{"left":0.16601562,"top":0.47847223,"width":0.01015625,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"+","depth":26,"bounds":{"left":0.17851563,"top":0.47708333,"width":0.006640625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Option","depth":27,"bounds":{"left":0.1875,"top":0.47847223,"width":0.01953125,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"+","depth":26,"bounds":{"left":0.209375,"top":0.47708333,"width":0.00703125,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I","depth":27,"bounds":{"left":0.21875,"top":0.47847223,"width":0.003125,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"on Mac).","depth":26,"bounds":{"left":0.11796875,"top":0.47708333,"width":0.11679687,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Click on the","depth":26,"bounds":{"left":0.11796875,"top":0.51875,"width":0.03515625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Console","depth":26,"bounds":{"left":0.153125,"top":0.51875,"width":0.024609376,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"tab.","depth":26,"bounds":{"left":0.17773438,"top":0.51875,"width":0.0125,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Look at the top right corner of the Console pane and click the","depth":26,"bounds":{"left":0.11796875,"top":0.54236114,"width":0.0984375,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gear icon","depth":26,"bounds":{"left":0.19609375,"top":0.56041664,"width":0.0296875,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(Console settings).","depth":26,"bounds":{"left":0.11796875,"top":0.56041664,"width":0.109375,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"In the dropdown menu, check the box next to","depth":26,"bounds":{"left":0.11796875,"top":0.6020833,"width":0.10898437,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Persist Logs","depth":26,"bounds":{"left":0.13945313,"top":0.6201389,"width":0.037109375,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":26,"bounds":{"left":0.1765625,"top":0.6201389,"width":0.0015625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Method 2: From the DevTools Settings","depth":23,"bounds":{"left":0.10390625,"top":0.66736114,"width":0.13242188,"height":0.016666668},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Method 2: From the DevTools Settings","depth":24,"bounds":{"left":0.10390625,"top":0.66875,"width":0.115625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open the Developer Tools (","depth":26,"bounds":{"left":0.11796875,"top":0.69166666,"width":0.07695313,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"F12","depth":27,"bounds":{"left":0.19726562,"top":0.69305557,"width":0.01015625,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":").","depth":26,"bounds":{"left":0.20976563,"top":0.69166666,"width":0.003515625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open the Settings menu by pressing","depth":26,"bounds":{"left":0.11796875,"top":0.7152778,"width":0.1046875,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"F1","depth":27,"bounds":{"left":0.225,"top":0.71666664,"width":0.00625,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"while the DevTools window is focused (or click the three dots","depth":26,"bounds":{"left":0.11796875,"top":0.7152778,"width":0.11796875,"height":0.050694443},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"...","depth":27,"bounds":{"left":0.1765625,"top":0.75277776,"width":0.01015625,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"in the top right of the DevTools panel and select","depth":26,"bounds":{"left":0.11796875,"top":0.7513889,"width":0.11601563,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Settings","depth":26,"bounds":{"left":0.11796875,"top":0.7875,"width":0.025390625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":").","depth":26,"bounds":{"left":0.14335938,"top":0.7875,"width":0.00390625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Scroll down to the","depth":26,"bounds":{"left":0.11796875,"top":0.8111111,"width":0.052734375,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Common Preferences","depth":26,"bounds":{"left":0.17070313,"top":0.8111111,"width":0.065625,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"section.","depth":26,"bounds":{"left":0.11796875,"top":0.8111111,"width":0.11835937,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Check the box that says","depth":26,"bounds":{"left":0.11796875,"top":0.8527778,"width":0.06992187,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Enable persistent logs","depth":26,"bounds":{"left":0.11796875,"top":0.8527778,"width":0.0921875,"height":0.03263889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":26,"bounds":{"left":0.16289063,"top":0.87083334,"width":0.001953125,"height":0.014583333},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Once this is turned on, your console history and network logs will remain visible across page reloads and navigation until you manually clear them by clicking the trash can icon.","depth":24,"bounds":{"left":0.10390625,"top":0.9,"width":0.1296875,"height":0.08680555},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXTextArea","text":"Enter a prompt for Gemini\nencrypted","depth":20,"bounds":{"left":0.109375,"top":0.8354167,"width":0.125,"height":0.016666668},"value":"Enter a prompt for Gemini\nencrypted","help_text":"","role_description":"text entry area","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXStaticText","text":"Enter a prompt for Gemini","depth":21,"bounds":{"left":0.1171875,"top":0.8354167,"width":0.08203125,"height":0.016666668},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"encrypted","depth":21,"bounds":{"left":0.10820313,"top":0.8354167,"width":0.0078125,"height":0.016666668},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open upload file menu","depth":20,"bounds":{"left":0.1046875,"top":0.86527777,"width":0.015625,"height":0.027777778},"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tools","depth":18,"bounds":{"left":0.1234375,"top":0.86527777,"width":0.015625,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open mode picker","depth":20,"bounds":{"left":0.190625,"top":0.8645833,"width":0.03046875,"height":0.027777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pro","depth":23,"bounds":{"left":0.196875,"top":0.87222224,"width":0.00859375,"height":0.013194445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXCheckBox","text":"Microphone","depth":19,"bounds":{"left":0.2234375,"top":0.8645833,"width":0.015625,"height":0.027777778},"role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.","depth":17,"bounds":{"left":0.10039063,"top":0.9097222,"width":0.14296874,"height":0.022222223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Your privacy & Gemini Opens in a new window","depth":17,"bounds":{"left":0.1484375,"top":0.93194443,"width":0.046875,"height":0.011111111},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Your privacy & Gemini","depth":18,"bounds":{"left":0.1484375,"top":0.93194443,"width":0.046875,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Opens in a new window","depth":19,"bounds":{"left":0.09335937,"top":0.93125,"width":0.05078125,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Summarize page","depth":7,"bounds":{"left":0.1,"top":0.96319443,"width":0.06289063,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Summarize page","depth":9,"bounds":{"left":0.10664062,"top":0.9673611,"width":0.049609374,"height":0.013888889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"install","depth":11,"bounds":{"left":0.23125,"top":0.9451389,"width":0.01875,"height":0.030555556},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"My Recordings","depth":10,"bounds":{"left":0.25703126,"top":0.10277778,"width":0.043359376,"height":0.045833334},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"My Recordings","depth":11,"bounds":{"left":0.2609375,"top":0.12013889,"width":0.035546876,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Everyone's Recordings","depth":10,"bounds":{"left":0.39648438,"top":0.10277778,"width":0.061328124,"height":0.045833334},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Everyone's Recordings","depth":11,"bounds":{"left":0.40039062,"top":0.12013889,"width":0.053515624,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Recordings","depth":13,"bounds":{"left":0.33945313,"top":0.23125,"width":0.0359375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Schedule","depth":9,"bounds":{"left":0.2589844,"top":0.2888889,"width":0.028515626,"height":0.023611112},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Schedule","depth":10,"bounds":{"left":0.2589844,"top":0.29305556,"width":0.028515626,"height":0.015277778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Invite Notetaker","depth":10,"bounds":{"left":0.40976563,"top":0.28680557,"width":0.051953126,"height":0.025},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXComboBox","text":"This Week","depth":10,"bounds":{"left":0.2589844,"top":0.3298611,"width":0.196875,"height":0.025694445},"value":"This Week","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"This Week","depth":12,"bounds":{"left":0.26328126,"top":0.33680555,"width":0.02578125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"My Schedule","depth":10,"bounds":{"left":0.2589844,"top":0.3625,"width":0.196875,"height":0.025694445},"value":"My Schedule","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"My Schedule","depth":12,"bounds":{"left":0.26328126,"top":0.36944443,"width":0.03125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"No Meetings","depth":12,"bounds":{"left":0.34179688,"top":0.48055556,"width":0.03125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Trending this month","depth":9,"bounds":{"left":0.26289064,"top":0.56319445,"width":0.054296874,"height":0.016666668},"help_text":"","role_description":"heading","subrole":"AXUnknown"}]...
|
5813269666865370460
|
-450536962629355004
|
idle
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
WORK, Google Account: [EMAIL]
Main menu
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
Copy prompt
Edit
You said firefox how to preseve console
You said
firefox how to preseve console
Listen
Show more options
Show thinking
Gemini said
Gemini said
To preserve your console logs in Firefox so they don't clear when you refresh or navigate to a new page, you need to enable the
Persist Logs
setting.
Here are the two easiest ways to do it:
Method 1: Directly from the Console Tab (Quickest)
Method 1: Directly from the Console Tab (Quickest)
Open the Developer Tools by pressing
F12
(or
Ctrl
+
Shift
+
I
on Windows/Linux,
Cmd
+
Option
+
I
on Mac).
Click on the
Console
tab.
Look at the top right corner of the Console pane and click the
Gear icon
(Console settings).
In the dropdown menu, check the box next to
Persist Logs
.
Method 2: From the DevTools Settings
Method 2: From the DevTools Settings
Open the Developer Tools (
F12
).
Open the Settings menu by pressing
F1
while the DevTools window is focused (or click the three dots
...
in the top right of the DevTools panel and select
Settings
).
Scroll down to the
Common Preferences
section.
Check the box that says
Enable persistent logs
.
Once this is turned on, your console history and network logs will remain visible across page reloads and navigation until you manually clear them by clicking the trash can icon.
Enter a prompt for Gemini
encrypted
Enter a prompt for Gemini
encrypted
Open upload file menu
Tools
Open mode picker
Pro
Microphone
Your Jiminny chats aren’t used to improve our models. Gemini is AI and can make mistakes, including about people.
Your privacy & Gemini Opens in a new window
Your privacy & Gemini
Opens in a new window
Summarize page
Summarize page
install
My Recordings
My Recordings
Everyone's Recordings
Everyone's Recordings
No Recordings
Schedule
Schedule
Invite Notetaker
This Week
This Week
My Schedule
My Schedule
No Meetings
Trending this month...
|
NULL
|
|
46969
|
NULL
|
0
|
2026-04-17T10:58:18.924024+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423498924_m1.jpg...
|
PhpStorm
|
faVsco.js – ~/jiminny/app/front-end/src/components faVsco.js – ~/jiminny/app/front-end/src/components/connect/connect.vue...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Code changed:
Hide
Sync Changes
Hide This Notification
33
2
19
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use HubSpot\Client\Crm\Deals\Model\CollectionResponseAssociatedId;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\Account;
use Exception;
use Jiminny\Component\DealInsights\Forecast\Forecast;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Contact;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Exceptions\CrmException;
use Jiminny\Models\Opportunity;
use Illuminate\Support\Collection;
use Jiminny\Models\Stage;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Services\Crm\Hubspot\DealFieldsService;
use Jiminny\Services\Crm\Hubspot\OpportunitySyncStrategy\HubspotSingleSyncStrategy;
use Jiminny\Services\Crm\Hubspot\WebhookSyncBatchProcessor;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Utils\CurrencyFormatter;
/**
* Optimized sync methods for better performance
* These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains
*/
trait OpportunitySyncTrait
{
private const int BATCH_SIZE = 100;
private const int BATCH_PROCESS_SIZE = 800;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected DealFieldsService $dealFieldsService;
private ?array $cachedClosedDealStages = null;
private array $cachedBusinessProcesses = [];
private array $cachedStages = [];
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$parameters['config'] = $this->config;
$syncCount = 0;
$reportedTotal = 0;
$lastSyncedId = [];
try {
foreach ($strategies as $strategyName => $syncStrategy) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .
$strategyName
);
$total = 0;
$lastId = null;
$buffer = [];
// HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies
foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {
$buffer[] = $hsOpportunity;
// process every 800 rows (fits < 1 000 association limit)
if (\count($buffer) >= self::BATCH_PROCESS_SIZE) {
$syncCount += $this->processOpportunityBatch($buffer);
$buffer = [];
}
}
// leftovers
if ($buffer) {
$syncCount += $this->processOpportunityBatch($buffer);
}
$reportedTotal += $total;
$lastSyncedId = $lastId;
}
} catch (\HubSpot\Client\Crm\Deals\ApiException | CrmException $e) {
$this->handleSyncException($e, $parameters);
}
$this->logger->info(
'[HubSpot] Synced opportunities',
[
'team' => $this->team->getId(),
'sync_count' => $syncCount,
'total' => $reportedTotal,
'last_synced_id' => $lastSyncedId,
]
);
return $reportedTotal;
}
private function handleSyncException(\Throwable $e, array $parameters): void
{
if (($parameters['since'] ?? null) instanceof Carbon) {
$parameters['since'] = $parameters['since']->toDateTimeString();
}
$parameters['config'] = $this->config->getId();
$this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [
'teamId' => $this->team->getUuid(),
'parameters' => $parameters,
'reason' => $e->getMessage(),
]);
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,
);
$parameters = [
'config' => $this->config,
'crm_id' => $crmId,
];
try {
if (! $strategy instanceof HubspotSingleSyncStrategy) {
throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');
}
$hsOpportunity = $strategy->fetchOpportunity($parameters);
} catch (\HubSpot\Client\Crm\Deals\ApiException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->getUuid(),
'crmId' => $crmId,
'reason' => $e->getMessage(),
]);
return null;
}
$hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);
return $this->importOrUpdateOpportunity($hsOpportunity);
}
/**
* Process webhook-collected opportunity batches.
*
* Drains Redis sets containing company CRM IDs collected from webhook events
* and dispatches ImportOpportunityBatch jobs for batch processing.
*
* @return int Number of opportunity IDs dispatched to jobs
*/
public function batchSyncOpportunities(): int
{
$configId = $this->team->getCrmConfiguration()->getId();
return $this->batchProcessor->processBatchesForObjectType(
WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,
$configId
);
}
/**
* Import a batch of opportunities by their CRM IDs.
* Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().
*
* @param array<string> $crmIds HubSpot deal CRM IDs
*
* @return array{success: array, failed_ids: array, errors?: array<string, string>}
*/
public function importOpportunityBatchByIds(array $crmIds): array
{
$fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);
$allDeals = [];
foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {
$deals = $this->client->getOpportunitiesByIds($chunk, $fields);
foreach ($deals as $deal) {
$allDeals[] = $deal;
}
}
// IDs not returned by HubSpot are likely deleted or inaccessible deals.
// These are not failures — retrying won't bring them back.
$fetchedIds = array_map('strval', array_column($allDeals, 'id'));
$notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));
if (! empty($notFoundIds)) {
$this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [
'teamId' => $this->team->getId(),
'notFoundCount' => \count($notFoundIds),
'notFoundIds' => $notFoundIds,
'requestedCount' => \count($crmIds),
'fetchedCount' => \count($allDeals),
]);
}
if (empty($allDeals)) {
return ['success' => [], 'failed_ids' => []];
}
return $this->importOpportunityBatch($allDeals);
}
private function getClosedDealStages(): array
{
if ($this->cachedClosedDealStages !== null) {
return $this->cachedClosedDealStages;
}
$stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);
$data = [
'lost' => [],
'won' => [],
];
foreach ($stages as $stage) {
if ($stage->probability == 0.00) {
$data['lost'][] = $stage->crm_provider_id;
}
if ($stage->probability == 100.00) {
$data['won'][] = $stage->crm_provider_id;
}
}
$this->cachedClosedDealStages = $data;
return $data;
}
/**
* Import deals into the database with pre-fetched associations.
*
* API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT
* caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()
* where Laravel retries the whole job with backoff. After all retries exhausted,
* failed() requeues all IDs to Redis.
*
* The per-deal loop catches exceptions individually. A deal can end up in three states:
* - success: imported/updated successfully
* - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)
* These are permanent issues — retrying won't fix them.
* - skipped (null): missing dependencies (no account, unknown pipeline/stage).
* This is acceptable — the deal cannot be imported until those exist.
*/
private function importOpportunityBatch(array $deals): array
{
$syncedOpportunities = [
'success' => [],
'failed_ids' => [],
];
$dealIds = array_column($deals, 'id');
// Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the
// queue job retries the whole batch and eventually requeues all deal IDs back to Redis.
try {
$companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');
$contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');
$associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);
$existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(
$this->config,
array_map('strval', $dealIds)
);
$existingCrmIdSet = array_flip($existingCrmIds);
} catch (\Throwable $e) {
$this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [
'teamId' => $this->team->getId(),
'dealCount' => count($dealIds),
'error' => $e->getMessage(),
]);
throw $e;
}
foreach ($deals as $deal) {
try {
$deal['associations'] = $this->prepareAssociationsForOpportunity(
$deal['id'],
$companyAssociations,
$contactAssociations,
$associationsData
);
$syncedOpportunity = $this->importOrUpdateOpportunity(
$deal,
isset($existingCrmIdSet[(string) $deal['id']])
);
if ($syncedOpportunity) {
$syncedOpportunities['success'][] = $syncedOpportunity;
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [
'teamId' => $this->team->getId(),
'crmId' => $deal['id'],
'error' => $e->getMessage(),
]);
$syncedOpportunities['failed_ids'][] = $deal['id'];
$syncedOpportunities['errors'][$deal['id']] = $e->getMessage();
}
}
return $syncedOpportunities;
}
/**
* Prepare associated entities for opportunities with optimized batch processing
* Returns structured data with CRM ID to DB ID mappings for each opportunity
*/
private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array
{
// Step 1: Collect all unique company and contact IDs from associations
$allCompanyIds = $this->flattenAssociationIds($companyAssociations);
$allContactIds = $this->flattenAssociationIds($contactAssociations);
// Step 2: Batch sync missing entities and get CRM ID to DB ID mappings
$companyIdMappings = [];
$contactIdMappings = [];
if (! empty($allCompanyIds)) {
$companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);
}
if (! empty($allContactIds)) {
$contactIdMappings = $this->prepareAssociatedContacts($allContactIds);
}
return [
'company_id_mappings' => $companyIdMappings,
'contact_id_mappings' => $contactIdMappings,
];
}
/**
* Flatten association data to get unique IDs
*/
private function flattenAssociationIds(array $associations): array
{
$ids = [];
foreach ($associations as $dealAssociations) {
if (is_array($dealAssociations)) {
foreach ($dealAssociations as $id) {
$ids[$id] = true;
}
}
}
return array_keys($ids);
}
/**
* Batch sync missing accounts
*/
private function prepareAssociatedAccounts(array $companyIds): array
{
// Find which accounts already exist
$existingAccounts = $this->crmEntityRepository
->findAccountsByExternalIds($this->config, $companyIds);
$existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();
$existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {
return [$account->getCrmProviderId() => $account->getId()];
})->toArray();
$missingCompanyIds = array_diff($companyIds, $existingCompanyIds);
if (empty($missingCompanyIds)) {
return $existingAccountsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [
'teamId' => $this->team->getUuid(),
'total_companies' => count($companyIds),
'existing_companies' => count($existingCompanyIds),
'missing_companies' => count($missingCompanyIds),
]);
// we already have limit on opportunity ids count
// Initialize variable before try block
$syncedAccountsData = [];
try {
$syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [
'size' => count($missingCompanyIds),
'error' => $e->getMessage(),
]);
$syncedAccountsData = [];
}
return $existingAccountsData + $syncedAccountsData;
}
/**
* Prepare associated contacts - find existing and sync missing ones
* Returns mapping of CRM ID to DB ID
*/
private function prepareAssociatedContacts(array $contactIds): array
{
// Find which contacts already exist
$existingContacts = $this->crmEntityRepository
->findContactsByExternalIds($this->config, $contactIds);
$existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();
// Create mapping for existing contacts
$existingContactsData = $existingContacts->mapWithKeys(function ($contact) {
return [$contact->getCrmProviderId() => $contact->getId()];
})->toArray();
$missingContactIds = array_diff($contactIds, $existingContactIds);
if (empty($missingContactIds)) {
return $existingContactsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [
'teamId' => $this->team->getUuid(),
'total_contacts' => count($contactIds),
'existing_contacts' => count($existingContactIds),
'missing_contacts' => count($missingContactIds),
]);
// Sync missing contacts using batch API
try {
$syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [
'size' => count($missingContactIds),
'error' => $e->getMessage(),
]);
$syncedContactsData = [];
}
return $existingContactsData + $syncedContactsData;
}
private function batchSyncCrmObjects(string $objectType, array $crmIds): array
{
$syncObjects = [];
$crmObjectIds = array_values($crmIds);
foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {
try {
$objects = $objectType === 'companies' ?
$this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :
$this->client->getContactsByIds($chunk, $this->getContactFields());
foreach ($objects as $objectId => $objectData) {
$this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [
'requested_count' => count($chunk),
'synced_count' => count($objects),
]);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [
'ids' => $chunk,
'error' => $e->getMessage(),
]);
}
}
return $syncObjects;
}
private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void
{
try {
$object = $objectType === 'companies' ?
$this->importAccount($objectData) :
$this->importContact($objectData);
if ($object) {
$syncObjects[$object->getCrmProviderId()] = $object->getId();
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [
'id' => $objectId,
'error' => $e->getMessage(),
]);
}
}
/**
* Prepare associations for a single opportunity
*
* The return value is an array with the following structure:
* [
* 'companies' => [
* $companyCrmId => $companyId,
* ...
* ],
* 'contacts' => [
* $contactCrmId => $contactId,
* ...
* ],
* 'account_id' => $accountId,
* ]
*/
private function prepareAssociationsForOpportunity(
string $oppCrmId,
array $companyAssociations,
array $contactAssociations,
array $associationsData
): array {
$associations = [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
$oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];
foreach ($oppCompanyIds as $companyCrmId) {
if (isset($associationsData['company_id_mappings'][$companyCrmId])) {
$associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];
// Set primary account (first company becomes primary account)
if ($associations['account_id'] === null) {
$associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];
}
}
}
$oppContactIds = $contactAssociations[$oppCrmId] ?? [];
foreach ($oppContactIds as $contactCrmId) {
if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {
$associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];
}
}
return $associations;
}
/**
* Update only associations for an opportunity
*/
private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void
{
// Update contact associations
$this->importOpportunityContacts($opportunity, $associations['contacts']);
// Update company (account) associations
$this->updateOpportunityAccount($opportunity, $associations['account_id']);
}
/**
* Remove all contact associations from an opportunity
*/
private function removeAllOpportunityContacts(Opportunity $opportunity): void
{
$currentCount = (int) $opportunity->contacts()->count();
if ($currentCount > 0) {
$opportunity->contacts()->detach();
$this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_count' => $currentCount,
]);
}
}
private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void
{
if ($accountId === null) {
// No account ID provided - keep current account
return;
}
$currentAccountId = $opportunity->getAccountId();
// Only update if account has changed
if ($currentAccountId !== $accountId) {
$opportunity->account_id = $accountId;
$opportunity->save();
$this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [
'opportunity_id' => $opportunity->getId(),
'old_account_id' => $currentAccountId,
'new_account_id' => $accountId,
]);
}
}
/**
* Find existing opportunities by external IDs (OPTIMIZED VERSION)
* Uses batch query for better performance
*/
private function findExistingOpportunities(array $crmIds): Collection
{
return $this->crmEntityRepository
->findOpportunitiesByExternalIds($this->config, $crmIds);
}
private function processOpportunityBatch(array $opportunities): int
{
$syncedOpportunities = $this->importOpportunityBatch($opportunities);
return count($syncedOpportunities['success'] ?? []);
}
/**
* Convert single deal associations from HubSpot format to internal format
* Handles both HubSpot SDK objects and array formats
*
* @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed
*
* @return array Processed associations with DB IDs
*/
private function convertDealAssociations(array $opportunityAssociations): array
{
$associations = $this->initializeAssociationsStructure();
if (empty($opportunityAssociations)) {
return $associations;
}
$associationIds = $this->extractAssociationIds($opportunityAssociations);
$this->processCompanyAssociations($associationIds, $associations);
$this->processContactAssociations($associationIds, $associations);
return $associations;
}
private function initializeAssociationsStructure(): array
{
return [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
}
private function extractAssociationIds(array $opportunityAssociations): array
{
$associationIds = [];
foreach ($opportunityAssociations as $type => $associationData) {
if (! empty($associationData)) {
$associationIds[$type] = $this->convertSingleDealAssociations($associationData);
}
}
return $associationIds;
}
private function processCompanyAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['companies'])) {
return;
}
$companyId = $associationIds['companies'][0];
$account = $this->findOrSyncAccount($companyId);
if ($account instanceof Account) {
$associations['companies'][$companyId] = $account->getId();
$associations['account_id'] = $account->getId();
}
}
private function processContactAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['contacts'])) {
return;
}
foreach ($associationIds['contacts'] as $contactId) {
$contact = $this->findOrSyncContact($contactId);
if ($contact instanceof Contact) {
$associations['contacts'][$contactId] = $contact->getId();
}
}
}
private function findOrSyncAccount(string $companyId): ?Account
{
$account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);
if (! $account instanceof Account) {
$account = $this->syncAccount($companyId);
}
return $account;
}
private function findOrSyncContact(string $contactId): ?Contact
{
$contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);
if (! $contact instanceof Contact) {
$contact = $this->syncContact($contactId);
}
return $contact;
}
private function convertSingleDealAssociations($opportunityAssociations = null): array
{
$associationData = [];
if ($opportunityAssociations === null) {
return $associationData;
}
// Handle array input (from extractAssociationIds)
if (is_array($opportunityAssociations)) {
return $opportunityAssociations;
}
// Handle CollectionResponseAssociatedId object
if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {
foreach ($opportunityAssociations->getResults() as $association) {
$associationData[] = $association->getId();
}
}
return $associationData;
}
private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity
{
if (empty($crmData['properties'])) {
return null;
}
$crmId = (string) $crmData['id'];
$properties = $crmData['properties'];
$associations = $crmData['associations'] ?? [];
$opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(
$this->config,
$crmId
);
if ($opportunityExists) {
return $this->updateOpportunity($crmId, $properties, $associations);
} else {
return $this->createOpportunity($crmId, $properties, $associations);
}
}
/**
* Create new opportunity
*/
private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity
{
$accountId = $this->resolveAccountId($associations);
if (! $accountId) {
return null;
}
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
if (! $businessProcess) {
return null;
}
$stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);
if (! $stage) {
return null;
}
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->importOpportunityContacts($opportunity, $associations['contacts']);
if ($opportunity->wasRecentlyCreated) {
MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());
}
return $opportunity;
}
/**
* Update existing opportunity
*/
private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity
{
$accountId = $this->resolveAccountId($associations);
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
$stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->updateOpportunityAssociations($opportunity, $associations);
return $opportunity;
}
private function resolveAccountId(array $associations): ?int
{
if (! empty($associations['accountId'])) {
return $associations['accountId'];
}
if (empty($associations)) {
return null;
}
// we can't resolve multiple account ids (currently SDK returns one company)
foreach ($associations['companies'] as $accountId) {
return $accountId;
}
return null;
}
private function buildOpportunityData(
array $properties,
?int $accountId,
?BusinessProcess $businessProcess,
?Stage $stage
): array {
$ownerId = null;
$profile = null;
if (! empty($properties['hubspot_owner_id'])) {
$ownerId = $properties['hubspot_owner_id'];
$profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);
}
$name = 'Unknown';
if (isset($properties['dealname'])) {
$name = mb_strimwidth($properties['dealname'], 0, 128);
}
$amount = $this->resolveAmount($properties);
$currency = $properties['deal_currency_code'] ?? null;
$closeDate = null;
if (! empty($properties['closedate'])) {
$closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');
}
$remotelyCreatedAt = null;
if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {
$date = $this->parseCleanDatetime($properties['createdate']);
$remotelyCreatedAt = $date?->format('Y-m-d H:i:s');
}
$closedStages = $this->getClosedDealStages();
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$data = [
'team_id' => $this->team->getId(),
'user_id' => $profile ? $profile->user_id : null,
'owner_id' => $ownerId,
'name' => $name,
'value' => ! empty($amount) ? $amount : null,
'currency_code' => CurrencyFormatter::formatCode($currency),
'close_date' => $closeDate,
'is_closed' => $isWon || $isLost,
'is_won' => $isWon,
'remotely_created_at' => $remotelyCreatedAt,
'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),
'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),
];
if ($accountId) {
$data['account_id'] = $accountId;
}
if ($stage) {
$data['stage_id'] = $stage->id;
}
if ($businessProcess) {
$recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);
if ($recordType) {
$data['record_type_id'] = $recordType->id;
}
}
return $data;
}
private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess
{
if ($pipelineId === null) {
return null;
}
if (isset($this->cachedBusinessProcesses[$pipelineId])) {
return $this->cachedBusinessProcesses[$pipelineId];
}
$businessProcess = $this->getBusinessProcess($pipelineId);
if (! $businessProcess instanceof BusinessProcess) {
$this->importStages();
$businessProcess = $this->getBusinessProcess($pipelineId);
}
if (! $businessProcess instanceof BusinessProcess) {
$this->logger->info(
'[HubSpot] Deal is not attached to a pipeline',
[
'pipeline' => $pipelineId]
);
}
$this->cachedBusinessProcesses[$pipelineId] = $businessProcess;
return $businessProcess;
}
private function getBusinessProcess(string $pipelineId): ?BusinessProcess
{
return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);
}
private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage
{
if (empty($stageId)) {
return null;
}
$cacheKey = $businessProcess->getId() . ':' . $stageId;
if (isset($this->cachedStages[$cacheKey])) {
return $this->cachedStages[$cacheKey];
}
$stage = $this->crmEntityRepository->getPipelineStageByConditions(
$businessProcess,
[
'crm_provider_id' => $stageId,
'type' => Stage::TYPE_OPPORTUNITY,
]
);
if ($stage === null) {
$this->importStages(null, $stageId);
}
if ($stage === null) {
$this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);
}
$this->cachedStages[$cacheKey] = $stage;
return $stage;
}
private function resolveAmount(array $properties): ?string
{
$amount = null;
if (! empty($properties['amount'])) {
$amount = str_replace(',', '', $properties['amount']);
}
if ($this->config->hasDefaultCurrencyFieldSet()) {
$valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();
$amount = $properties[$valueFieldName] ?? $amount;
}
return $amount;
}
private function parseCleanDatetime(string $datetime): ?Carbon
{
// Treat pre-1980 values as invalid
$minValidDate = Carbon::parse('1980-01-01 00:00:00');
try {
$date = Carbon::parse($datetime);
if ($minValidDate->gt($date)) {
return null;
}
return $date;
} catch (Exception) {
return null; // On parse error, treat as null
}
}
private function resolveDealProbability(?string $stageProbability): int
{
if ($stageProbability === null) {
return 0;
}
$probability = (float) $stageProbability;
return $probability > 1 ? 0 : (int) ($probability * 100);
}
private function resolveForecastCategory(?string $forecastCategory): string
{
if (! $forecastCategory) {
return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;
}
$forecastCategory = str_replace('_', ' ', $forecastCategory);
return ucwords(strtolower($forecastCategory));
}
private function importExternalFieldData(array $properties, int $opportunityId): void
{
$crmFields = $this->getOpportunitySyncableFields();
$this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);
}
private function importOpportunityContacts(Opportunity $opportunity, array $associations): void
{
// Handle empty or missing contact associations
if (empty($associations)) {
// Remove all existing contact associations if none provided
$this->removeAllOpportunityContacts($opportunity);
return;
}
// Use differential sync approach for better performance and accuracy
$this->syncOpportunityContactsDifferential($opportunity, $associations);
}
/**
* Sync opportunity contacts using differential approach
* This compares current vs new associations and only makes necessary changes
*/
private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void
{
$currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);
$contactAssociationIds = array_keys($contactAssociations);
$contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);
$contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);
if (empty($contactsToAdd) && empty($contactsToRemove)) {
return;
}
$this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);
$this->removeContactAssociations($opportunity, $contactsToRemove);
$this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);
}
private function getCurrentContactCrmIds(Opportunity $opportunity): array
{
return $opportunity->contacts()
->pluck('contacts.crm_provider_id')
->toArray();
}
private function logContactAssociationChanges(
Opportunity $opportunity,
array $currentContactCrmIds,
array $contactAssociations,
array $contactsToAdd,
array $contactsToRemove
): void {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [
'opportunity_id' => $opportunity->getId(),
'current_contacts' => $currentContactCrmIds,
'new_contacts' => $contactAssociations,
'contacts_to_add' => $contactsToAdd,
'contacts_to_remove' => $contactsToRemove,
]);
}
private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void
{
if (empty($contactsToRemove)) {
return;
}
$contactsToDetach = $opportunity->contacts()
->whereIn('contacts.crm_provider_id', $contactsToRemove)
->pluck('contacts.id')
->toArray();
if (! empty($contactsToDetach)) {
$opportunity->contacts()->detach($contactsToDetach);
$this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_contact_crm_ids' => $contactsToRemove,
'removed_contact_count' => count($contactsToDetach),
]);
}
}
private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void
{
if (empty($contactsToAdd)) {
return;
}
$contactsAdded = [];
foreach ($contactsToAdd as $crmId) {
$id = $contactAssociations[$crmId];
if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {
$contactsAdded[] = $crmId;
}
}
$this->logAddedContacts($opportunity, $contactsAdded);
}
private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool
{
try {
$contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);
if (! $contact) {
return false;
}
return $this->performContactAttachment($opportunity, $contact, $crmId);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [
'opportunity_id' => $opportunity->getId(),
'contact_crm_id' => $crmId,
'error' => $e->getMessage(),
]);
return false;
}
}
private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool
{
try {
$opportunity->contacts()->attach($contact->getId(), [
'crm_provider_id' => $crmId,
]);
return true;
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [
'contact_id' => $contact->getId(),
'contact_crm_id' => $crmId,
'opportunity_id' => $opportunity->getId(),
]);
return false;
}
throw $e;
}
}
private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void
{
if (! empty($contactsAdded)) {
$this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [
'opportunity_id' => $opportunity->getId(),
'contacts_to_add_count' => count($contactsAdded),
'added_contact_crm_ids' => $contactsAdded,
'added_contacts_count' => count($contactsAdded),
]);
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<template>
<WelcomeLayout
title="Account disconnected"
textPosition="center"
:icon="faUnlink"
:class="$style.layout"
>
<div :class="$style.container" v-if="providersLoaded">
<p>
<strong>
It looks like your {{ localProvider.displayName }} account has become
disconnected
</strong>
</p>
<p :class="$style.small">Please re-connect to continue</p>
<p v-if="isInIframe">
We'll open the {{ localProvider.displayName }} authentication in a new
tab. Please return here and refresh the page once complete
</p>
<GoogleLikeButton
v-if="localProvider.viaIntegrationApp && crmTokenLoaded"
as="a"
:key="localProvider.name"
:brand-logo="localProvider.name"
:class="$style.connectButton"
@click="integrationAppOnClick"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
<GoogleLikeButton
v-if="!localProvider.viaIntegrationApp"
as="a"
:key="localProvider.name"
:href="`/auth/redirect/${localProvider.name}`"
:target="target"
:brand-logo="localProvider.name"
:class="$style.connectButton"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
</div>
<BuildInfo />
<KioskBanner />
</WelcomeLayout>
</template>
<script>
import window from "window";
import axios from "axios";
import { faUnlink } from "@fortawesome/pro-regular-svg-icons";
import isInIframe from "@/utils/isInIframe";
import BuildInfo from "@/components/layout/BuildInfo/BuildInfo.vue";
import KioskBanner from "@/components/shared/KioskBanner/KioskBanner.vue";
import WelcomeLayout from "@/components/layout/WelcomeLayout/WelcomeLayout.vue";
import GoogleLikeButton from "@/components/shared/Buttons/GoogleLikeButton.vue";
import { showSnackbarError, normalizeError } from "@/utils/index";
import { IntegrationAppClient } from "@integration-app/sdk";
export default {
name: "ConnectPage",
components: {
BuildInfo,
KioskBanner,
WelcomeLayout,
GoogleLikeButton,
},
data() {
return {
...window.connectData,
crmToken: null,
faUnlink,
isInIframe,
providers: [],
providersLoaded: false,
crmTokenLoaded: false,
};
},
computed: {
localProvider() {
return this.providers.find((e) => e.name === this.provider);
},
target() {
return this.isInIframe ? "_blank" : null;
},
},
created() {
this.getProviders();
},
mounted() {
this.showErrors();
},
watch: {
providersLoaded() {
if (this.providersLoaded) {
this.prepareIntegrationAppConnection();
}
},
},
methods: {
showErrors() {
if (!this.error) return;
showSnackbarError(this.error, undefined, undefined, false);
},
unwrapEntityResponse({ data }) {
return data.map(({ icon, name, displayName, viaIntegrationApp }) => {
return { icon, name, displayName, viaIntegrationApp };
});
},
async getProviders() {
try {
const response = await axios.get("/api/v1/connect-providers");
this.providers = this.unwrapEntityResponse(response);
this.providersLoaded = true;
} catch {
showSnackbarError(
"An error occurred, while loading form data (connect providers).",
);
}
},
async prepareIntegrationAppConnection() {
if (this.localProvider.viaIntegrationApp) {
try {
const response = await axios.get("/api/v1/integration-app-token");
this.crmToken = response.data.token;
this.crmTokenLoaded = true;
} catch (error) {
console.log(error);
showSnackbarError(
`An error occurred while preparing the page.
Try refreshing, if the error persists get in touch with the Jiminny team.`,
);
}
}
},
async integrationAppOnClick() {
console.log('[IntegrationApp] integrationAppOnClick called');
const integrationApp = new IntegrationAppClient({
token: this.crmToken,
});
const connection = await integrationApp
.integration(this.localProvider.name)
.openNewConnection({
showPoweredBy: false,
allowMultipleConnections: false,
}).catch((err) => {
console.log('[IntegrationApp] openNewConnection rejected:', err);
return null;
});
console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));
// [IntegrationApp] openNewConnection resolved: {
// "id":"69e0b41a67d0068c2ca0b48e",
// "name":"Zoho CRM",
// "userId":"1ece66c8-feb1-4df1-b321-21607daf4623",
// "tenantId":"69e0b3faef3e7b6248189289",
// "isTest":false,
// "connected":true,
// "state":"READY",
// "errors":[],
// "integrationId":"66fe6c913202f3a165e3c14d",
// "externalAppId":"6671653e7e2d642e4e41b0fa",
// "authOptionKey":"",
// "createdAt":"2026-04-16T10:04:10.420Z",
// "updatedAt":"2026-04-16T10:04:10.575Z",
// "retryAttempts":0,
// "isDeactivated":false
// }
if (connection && connection.disconnected !== true && connection.connected !== false) {
console.log('[IntegrationApp] connection condition matched');
try {
const saveRequest = await axios.post(
"/api/v1/integration-app-connect",
);
if (saveRequest.data && saveRequest.data.success === true) {
/** If all is good refresh the page here */
window.location = "/dashboard";
return;
}
throw new Error(saveRequest.data.message);
} catch (error) {
console.log(error);
showSnackbarError(normalizeError(error));
}
}
},
},
};
</script>
<style module lang="less" src="./connect.less"></style>
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.024444444},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2/4","depth":4,"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"33","depth":4,"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\CollectionResponseAssociatedId;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\Account;\nuse Exception;\nuse Jiminny\\Component\\DealInsights\\Forecast\\Forecast;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Models\\Opportunity;\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Repositories\\Crm\\CrmEntityRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DealFieldsService;\nuse Jiminny\\Services\\Crm\\Hubspot\\OpportunitySyncStrategy\\HubspotSingleSyncStrategy;\nuse Jiminny\\Services\\Crm\\Hubspot\\WebhookSyncBatchProcessor;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Utils\\CurrencyFormatter;\n\n/**\n * Optimized sync methods for better performance\n * These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains\n */\ntrait OpportunitySyncTrait\n{\n private const int BATCH_SIZE = 100;\n private const int BATCH_PROCESS_SIZE = 800;\n\n protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n protected CrmEntityRepository $crmEntityRepository;\n protected DealFieldsService $dealFieldsService;\n\n private ?array $cachedClosedDealStages = null;\n private array $cachedBusinessProcesses = [];\n private array $cachedStages = [];\n\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n $parameters['config'] = $this->config;\n $syncCount = 0;\n $reportedTotal = 0;\n $lastSyncedId = [];\n\n try {\n foreach ($strategies as $strategyName => $syncStrategy) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .\n $strategyName\n );\n\n $total = 0;\n $lastId = null;\n $buffer = [];\n\n // HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies\n foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {\n $buffer[] = $hsOpportunity;\n\n // process every 800 rows (fits < 1 000 association limit)\n if (\\count($buffer) >= self::BATCH_PROCESS_SIZE) {\n $syncCount += $this->processOpportunityBatch($buffer);\n $buffer = [];\n }\n }\n\n // leftovers\n if ($buffer) {\n $syncCount += $this->processOpportunityBatch($buffer);\n }\n\n $reportedTotal += $total;\n $lastSyncedId = $lastId;\n }\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException | CrmException $e) {\n $this->handleSyncException($e, $parameters);\n }\n\n $this->logger->info(\n '[HubSpot] Synced opportunities',\n [\n 'team' => $this->team->getId(),\n 'sync_count' => $syncCount,\n 'total' => $reportedTotal,\n 'last_synced_id' => $lastSyncedId,\n ]\n );\n\n return $reportedTotal;\n }\n\n private function handleSyncException(\\Throwable $e, array $parameters): void\n {\n if (($parameters['since'] ?? null) instanceof Carbon) {\n $parameters['since'] = $parameters['since']->toDateTimeString();\n }\n $parameters['config'] = $this->config->getId();\n\n $this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [\n 'teamId' => $this->team->getUuid(),\n 'parameters' => $parameters,\n 'reason' => $e->getMessage(),\n ]);\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,\n );\n\n $parameters = [\n 'config' => $this->config,\n 'crm_id' => $crmId,\n ];\n\n try {\n if (! $strategy instanceof HubspotSingleSyncStrategy) {\n throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');\n }\n\n $hsOpportunity = $strategy->fetchOpportunity($parameters);\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->getUuid(),\n 'crmId' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);\n\n return $this->importOrUpdateOpportunity($hsOpportunity);\n }\n\n /**\n * Process webhook-collected opportunity batches.\n *\n * Drains Redis sets containing company CRM IDs collected from webhook events\n * and dispatches ImportOpportunityBatch jobs for batch processing.\n *\n * @return int Number of opportunity IDs dispatched to jobs\n */\n public function batchSyncOpportunities(): int\n {\n $configId = $this->team->getCrmConfiguration()->getId();\n\n return $this->batchProcessor->processBatchesForObjectType(\n WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,\n $configId\n );\n }\n\n /**\n * Import a batch of opportunities by their CRM IDs.\n * Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().\n *\n * @param array<string> $crmIds HubSpot deal CRM IDs\n *\n * @return array{success: array, failed_ids: array, errors?: array<string, string>}\n */\n public function importOpportunityBatchByIds(array $crmIds): array\n {\n $fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);\n\n $allDeals = [];\n foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {\n $deals = $this->client->getOpportunitiesByIds($chunk, $fields);\n foreach ($deals as $deal) {\n $allDeals[] = $deal;\n }\n }\n\n // IDs not returned by HubSpot are likely deleted or inaccessible deals.\n // These are not failures — retrying won't bring them back.\n $fetchedIds = array_map('strval', array_column($allDeals, 'id'));\n $notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));\n\n if (! empty($notFoundIds)) {\n $this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [\n 'teamId' => $this->team->getId(),\n 'notFoundCount' => \\count($notFoundIds),\n 'notFoundIds' => $notFoundIds,\n 'requestedCount' => \\count($crmIds),\n 'fetchedCount' => \\count($allDeals),\n ]);\n }\n\n if (empty($allDeals)) {\n return ['success' => [], 'failed_ids' => []];\n }\n\n return $this->importOpportunityBatch($allDeals);\n }\n\n private function getClosedDealStages(): array\n {\n if ($this->cachedClosedDealStages !== null) {\n return $this->cachedClosedDealStages;\n }\n\n $stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);\n $data = [\n 'lost' => [],\n 'won' => [],\n ];\n\n foreach ($stages as $stage) {\n if ($stage->probability == 0.00) {\n $data['lost'][] = $stage->crm_provider_id;\n }\n if ($stage->probability == 100.00) {\n $data['won'][] = $stage->crm_provider_id;\n }\n }\n\n $this->cachedClosedDealStages = $data;\n\n return $data;\n }\n\n /**\n * Import deals into the database with pre-fetched associations.\n *\n * API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT\n * caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()\n * where Laravel retries the whole job with backoff. After all retries exhausted,\n * failed() requeues all IDs to Redis.\n *\n * The per-deal loop catches exceptions individually. A deal can end up in three states:\n * - success: imported/updated successfully\n * - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)\n * These are permanent issues — retrying won't fix them.\n * - skipped (null): missing dependencies (no account, unknown pipeline/stage).\n * This is acceptable — the deal cannot be imported until those exist.\n */\n private function importOpportunityBatch(array $deals): array\n {\n $syncedOpportunities = [\n 'success' => [],\n 'failed_ids' => [],\n ];\n $dealIds = array_column($deals, 'id');\n\n // Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the\n // queue job retries the whole batch and eventually requeues all deal IDs back to Redis.\n try {\n $companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');\n $contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');\n\n $associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);\n\n $existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(\n $this->config,\n array_map('strval', $dealIds)\n );\n $existingCrmIdSet = array_flip($existingCrmIds);\n } catch (\\Throwable $e) {\n $this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [\n 'teamId' => $this->team->getId(),\n 'dealCount' => count($dealIds),\n 'error' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n foreach ($deals as $deal) {\n try {\n $deal['associations'] = $this->prepareAssociationsForOpportunity(\n $deal['id'],\n $companyAssociations,\n $contactAssociations,\n $associationsData\n );\n\n $syncedOpportunity = $this->importOrUpdateOpportunity(\n $deal,\n isset($existingCrmIdSet[(string) $deal['id']])\n );\n if ($syncedOpportunity) {\n $syncedOpportunities['success'][] = $syncedOpportunity;\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [\n 'teamId' => $this->team->getId(),\n 'crmId' => $deal['id'],\n 'error' => $e->getMessage(),\n ]);\n $syncedOpportunities['failed_ids'][] = $deal['id'];\n $syncedOpportunities['errors'][$deal['id']] = $e->getMessage();\n }\n }\n\n return $syncedOpportunities;\n }\n\n /**\n * Prepare associated entities for opportunities with optimized batch processing\n * Returns structured data with CRM ID to DB ID mappings for each opportunity\n */\n private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array\n {\n // Step 1: Collect all unique company and contact IDs from associations\n $allCompanyIds = $this->flattenAssociationIds($companyAssociations);\n $allContactIds = $this->flattenAssociationIds($contactAssociations);\n\n // Step 2: Batch sync missing entities and get CRM ID to DB ID mappings\n $companyIdMappings = [];\n $contactIdMappings = [];\n\n if (! empty($allCompanyIds)) {\n $companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);\n }\n\n if (! empty($allContactIds)) {\n $contactIdMappings = $this->prepareAssociatedContacts($allContactIds);\n }\n\n return [\n 'company_id_mappings' => $companyIdMappings,\n 'contact_id_mappings' => $contactIdMappings,\n ];\n }\n\n /**\n * Flatten association data to get unique IDs\n */\n private function flattenAssociationIds(array $associations): array\n {\n $ids = [];\n foreach ($associations as $dealAssociations) {\n if (is_array($dealAssociations)) {\n foreach ($dealAssociations as $id) {\n $ids[$id] = true;\n }\n }\n }\n\n return array_keys($ids);\n }\n\n /**\n * Batch sync missing accounts\n */\n private function prepareAssociatedAccounts(array $companyIds): array\n {\n // Find which accounts already exist\n $existingAccounts = $this->crmEntityRepository\n ->findAccountsByExternalIds($this->config, $companyIds);\n\n $existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();\n\n $existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {\n return [$account->getCrmProviderId() => $account->getId()];\n })->toArray();\n\n $missingCompanyIds = array_diff($companyIds, $existingCompanyIds);\n\n if (empty($missingCompanyIds)) {\n return $existingAccountsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [\n 'teamId' => $this->team->getUuid(),\n 'total_companies' => count($companyIds),\n 'existing_companies' => count($existingCompanyIds),\n 'missing_companies' => count($missingCompanyIds),\n ]);\n\n // we already have limit on opportunity ids count\n // Initialize variable before try block\n $syncedAccountsData = [];\n\n try {\n $syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [\n 'size' => count($missingCompanyIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedAccountsData = [];\n }\n\n return $existingAccountsData + $syncedAccountsData;\n }\n\n /**\n * Prepare associated contacts - find existing and sync missing ones\n * Returns mapping of CRM ID to DB ID\n */\n private function prepareAssociatedContacts(array $contactIds): array\n {\n // Find which contacts already exist\n $existingContacts = $this->crmEntityRepository\n ->findContactsByExternalIds($this->config, $contactIds);\n\n $existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();\n\n // Create mapping for existing contacts\n $existingContactsData = $existingContacts->mapWithKeys(function ($contact) {\n return [$contact->getCrmProviderId() => $contact->getId()];\n })->toArray();\n\n $missingContactIds = array_diff($contactIds, $existingContactIds);\n\n if (empty($missingContactIds)) {\n return $existingContactsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [\n 'teamId' => $this->team->getUuid(),\n 'total_contacts' => count($contactIds),\n 'existing_contacts' => count($existingContactIds),\n 'missing_contacts' => count($missingContactIds),\n ]);\n\n // Sync missing contacts using batch API\n try {\n $syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [\n 'size' => count($missingContactIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedContactsData = [];\n }\n\n return $existingContactsData + $syncedContactsData;\n }\n\n private function batchSyncCrmObjects(string $objectType, array $crmIds): array\n {\n $syncObjects = [];\n $crmObjectIds = array_values($crmIds);\n\n foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {\n try {\n $objects = $objectType === 'companies' ?\n $this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :\n $this->client->getContactsByIds($chunk, $this->getContactFields());\n\n foreach ($objects as $objectId => $objectData) {\n $this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [\n 'requested_count' => count($chunk),\n 'synced_count' => count($objects),\n ]);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [\n 'ids' => $chunk,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n return $syncObjects;\n }\n\n private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void\n {\n try {\n $object = $objectType === 'companies' ?\n $this->importAccount($objectData) :\n $this->importContact($objectData);\n\n if ($object) {\n $syncObjects[$object->getCrmProviderId()] = $object->getId();\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [\n 'id' => $objectId,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * Prepare associations for a single opportunity\n *\n * The return value is an array with the following structure:\n * [\n * 'companies' => [\n * $companyCrmId => $companyId,\n * ...\n * ],\n * 'contacts' => [\n * $contactCrmId => $contactId,\n * ...\n * ],\n * 'account_id' => $accountId,\n * ]\n */\n private function prepareAssociationsForOpportunity(\n string $oppCrmId,\n array $companyAssociations,\n array $contactAssociations,\n array $associationsData\n ): array {\n $associations = [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n\n $oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];\n foreach ($oppCompanyIds as $companyCrmId) {\n if (isset($associationsData['company_id_mappings'][$companyCrmId])) {\n $associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];\n\n // Set primary account (first company becomes primary account)\n if ($associations['account_id'] === null) {\n $associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];\n }\n }\n }\n\n $oppContactIds = $contactAssociations[$oppCrmId] ?? [];\n foreach ($oppContactIds as $contactCrmId) {\n if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {\n $associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];\n }\n }\n\n return $associations;\n }\n\n /**\n * Update only associations for an opportunity\n */\n private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void\n {\n // Update contact associations\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n // Update company (account) associations\n $this->updateOpportunityAccount($opportunity, $associations['account_id']);\n }\n\n /**\n * Remove all contact associations from an opportunity\n */\n private function removeAllOpportunityContacts(Opportunity $opportunity): void\n {\n $currentCount = (int) $opportunity->contacts()->count();\n\n if ($currentCount > 0) {\n $opportunity->contacts()->detach();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_count' => $currentCount,\n ]);\n }\n }\n\n private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void\n {\n if ($accountId === null) {\n // No account ID provided - keep current account\n return;\n }\n\n $currentAccountId = $opportunity->getAccountId();\n\n // Only update if account has changed\n if ($currentAccountId !== $accountId) {\n $opportunity->account_id = $accountId;\n $opportunity->save();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [\n 'opportunity_id' => $opportunity->getId(),\n 'old_account_id' => $currentAccountId,\n 'new_account_id' => $accountId,\n ]);\n }\n }\n\n /**\n * Find existing opportunities by external IDs (OPTIMIZED VERSION)\n * Uses batch query for better performance\n */\n private function findExistingOpportunities(array $crmIds): Collection\n {\n return $this->crmEntityRepository\n ->findOpportunitiesByExternalIds($this->config, $crmIds);\n }\n\n private function processOpportunityBatch(array $opportunities): int\n {\n $syncedOpportunities = $this->importOpportunityBatch($opportunities);\n\n return count($syncedOpportunities['success'] ?? []);\n }\n\n /**\n * Convert single deal associations from HubSpot format to internal format\n * Handles both HubSpot SDK objects and array formats\n *\n * @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed\n *\n * @return array Processed associations with DB IDs\n */\n private function convertDealAssociations(array $opportunityAssociations): array\n {\n $associations = $this->initializeAssociationsStructure();\n\n if (empty($opportunityAssociations)) {\n return $associations;\n }\n\n $associationIds = $this->extractAssociationIds($opportunityAssociations);\n\n $this->processCompanyAssociations($associationIds, $associations);\n $this->processContactAssociations($associationIds, $associations);\n\n return $associations;\n }\n\n private function initializeAssociationsStructure(): array\n {\n return [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n }\n\n private function extractAssociationIds(array $opportunityAssociations): array\n {\n $associationIds = [];\n\n foreach ($opportunityAssociations as $type => $associationData) {\n if (! empty($associationData)) {\n $associationIds[$type] = $this->convertSingleDealAssociations($associationData);\n }\n }\n\n return $associationIds;\n }\n\n private function processCompanyAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['companies'])) {\n return;\n }\n\n $companyId = $associationIds['companies'][0];\n $account = $this->findOrSyncAccount($companyId);\n\n if ($account instanceof Account) {\n $associations['companies'][$companyId] = $account->getId();\n $associations['account_id'] = $account->getId();\n }\n }\n\n private function processContactAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['contacts'])) {\n return;\n }\n\n foreach ($associationIds['contacts'] as $contactId) {\n $contact = $this->findOrSyncContact($contactId);\n\n if ($contact instanceof Contact) {\n $associations['contacts'][$contactId] = $contact->getId();\n }\n }\n }\n\n private function findOrSyncAccount(string $companyId): ?Account\n {\n $account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);\n\n if (! $account instanceof Account) {\n $account = $this->syncAccount($companyId);\n }\n\n return $account;\n }\n\n private function findOrSyncContact(string $contactId): ?Contact\n {\n $contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);\n\n if (! $contact instanceof Contact) {\n $contact = $this->syncContact($contactId);\n }\n\n return $contact;\n }\n\n private function convertSingleDealAssociations($opportunityAssociations = null): array\n {\n $associationData = [];\n\n if ($opportunityAssociations === null) {\n return $associationData;\n }\n\n // Handle array input (from extractAssociationIds)\n if (is_array($opportunityAssociations)) {\n return $opportunityAssociations;\n }\n\n // Handle CollectionResponseAssociatedId object\n if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {\n foreach ($opportunityAssociations->getResults() as $association) {\n $associationData[] = $association->getId();\n }\n }\n\n return $associationData;\n }\n\n private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity\n {\n if (empty($crmData['properties'])) {\n return null;\n }\n\n $crmId = (string) $crmData['id'];\n $properties = $crmData['properties'];\n $associations = $crmData['associations'] ?? [];\n\n $opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(\n $this->config,\n $crmId\n );\n\n if ($opportunityExists) {\n return $this->updateOpportunity($crmId, $properties, $associations);\n } else {\n return $this->createOpportunity($crmId, $properties, $associations);\n }\n }\n\n /**\n * Create new opportunity\n */\n private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n if (! $accountId) {\n return null;\n }\n\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n if (! $businessProcess) {\n return null;\n }\n\n $stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);\n if (! $stage) {\n return null;\n }\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n }\n\n /**\n * Update existing opportunity\n */\n private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n $stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->updateOpportunityAssociations($opportunity, $associations);\n\n return $opportunity;\n }\n\n private function resolveAccountId(array $associations): ?int\n {\n if (! empty($associations['accountId'])) {\n return $associations['accountId'];\n }\n\n if (empty($associations)) {\n return null;\n }\n\n // we can't resolve multiple account ids (currently SDK returns one company)\n foreach ($associations['companies'] as $accountId) {\n return $accountId;\n }\n\n return null;\n }\n\n private function buildOpportunityData(\n array $properties,\n ?int $accountId,\n ?BusinessProcess $businessProcess,\n ?Stage $stage\n ): array {\n $ownerId = null;\n $profile = null;\n if (! empty($properties['hubspot_owner_id'])) {\n $ownerId = $properties['hubspot_owner_id'];\n $profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);\n }\n\n $name = 'Unknown';\n if (isset($properties['dealname'])) {\n $name = mb_strimwidth($properties['dealname'], 0, 128);\n }\n\n $amount = $this->resolveAmount($properties);\n $currency = $properties['deal_currency_code'] ?? null;\n\n $closeDate = null;\n if (! empty($properties['closedate'])) {\n $closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');\n }\n\n $remotelyCreatedAt = null;\n if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {\n $date = $this->parseCleanDatetime($properties['createdate']);\n $remotelyCreatedAt = $date?->format('Y-m-d H:i:s');\n }\n\n $closedStages = $this->getClosedDealStages();\n $isWon = in_array($properties['dealstage'], $closedStages['won']);\n $isLost = in_array($properties['dealstage'], $closedStages['lost']);\n\n $data = [\n 'team_id' => $this->team->getId(),\n 'user_id' => $profile ? $profile->user_id : null,\n 'owner_id' => $ownerId,\n 'name' => $name,\n 'value' => ! empty($amount) ? $amount : null,\n 'currency_code' => CurrencyFormatter::formatCode($currency),\n 'close_date' => $closeDate,\n 'is_closed' => $isWon || $isLost,\n 'is_won' => $isWon,\n 'remotely_created_at' => $remotelyCreatedAt,\n 'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),\n 'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),\n ];\n\n if ($accountId) {\n $data['account_id'] = $accountId;\n }\n\n if ($stage) {\n $data['stage_id'] = $stage->id;\n }\n\n if ($businessProcess) {\n $recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);\n if ($recordType) {\n $data['record_type_id'] = $recordType->id;\n }\n }\n\n return $data;\n }\n\n private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess\n {\n if ($pipelineId === null) {\n return null;\n }\n\n if (isset($this->cachedBusinessProcesses[$pipelineId])) {\n return $this->cachedBusinessProcesses[$pipelineId];\n }\n\n $businessProcess = $this->getBusinessProcess($pipelineId);\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->importStages();\n $businessProcess = $this->getBusinessProcess($pipelineId);\n }\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->logger->info(\n '[HubSpot] Deal is not attached to a pipeline',\n [\n 'pipeline' => $pipelineId]\n );\n }\n\n $this->cachedBusinessProcesses[$pipelineId] = $businessProcess;\n\n return $businessProcess;\n }\n\n private function getBusinessProcess(string $pipelineId): ?BusinessProcess\n {\n return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);\n }\n\n private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage\n {\n if (empty($stageId)) {\n return null;\n }\n\n $cacheKey = $businessProcess->getId() . ':' . $stageId;\n if (isset($this->cachedStages[$cacheKey])) {\n return $this->cachedStages[$cacheKey];\n }\n\n $stage = $this->crmEntityRepository->getPipelineStageByConditions(\n $businessProcess,\n [\n 'crm_provider_id' => $stageId,\n 'type' => Stage::TYPE_OPPORTUNITY,\n ]\n );\n\n if ($stage === null) {\n $this->importStages(null, $stageId);\n }\n\n if ($stage === null) {\n $this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);\n }\n\n $this->cachedStages[$cacheKey] = $stage;\n\n return $stage;\n }\n\n private function resolveAmount(array $properties): ?string\n {\n $amount = null;\n if (! empty($properties['amount'])) {\n $amount = str_replace(',', '', $properties['amount']);\n }\n\n if ($this->config->hasDefaultCurrencyFieldSet()) {\n $valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();\n $amount = $properties[$valueFieldName] ?? $amount;\n }\n\n return $amount;\n }\n\n private function parseCleanDatetime(string $datetime): ?Carbon\n {\n // Treat pre-1980 values as invalid\n $minValidDate = Carbon::parse('1980-01-01 00:00:00');\n\n try {\n $date = Carbon::parse($datetime);\n\n if ($minValidDate->gt($date)) {\n return null;\n }\n\n return $date;\n } catch (Exception) {\n return null; // On parse error, treat as null\n }\n }\n\n private function resolveDealProbability(?string $stageProbability): int\n {\n if ($stageProbability === null) {\n return 0;\n }\n\n $probability = (float) $stageProbability;\n\n return $probability > 1 ? 0 : (int) ($probability * 100);\n }\n\n private function resolveForecastCategory(?string $forecastCategory): string\n {\n if (! $forecastCategory) {\n return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;\n }\n\n $forecastCategory = str_replace('_', ' ', $forecastCategory);\n\n return ucwords(strtolower($forecastCategory));\n }\n\n private function importExternalFieldData(array $properties, int $opportunityId): void\n {\n $crmFields = $this->getOpportunitySyncableFields();\n $this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);\n }\n\n private function importOpportunityContacts(Opportunity $opportunity, array $associations): void\n {\n // Handle empty or missing contact associations\n if (empty($associations)) {\n // Remove all existing contact associations if none provided\n $this->removeAllOpportunityContacts($opportunity);\n\n return;\n }\n\n // Use differential sync approach for better performance and accuracy\n $this->syncOpportunityContactsDifferential($opportunity, $associations);\n }\n\n /**\n * Sync opportunity contacts using differential approach\n * This compares current vs new associations and only makes necessary changes\n */\n private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void\n {\n $currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);\n $contactAssociationIds = array_keys($contactAssociations);\n\n $contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);\n $contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);\n\n if (empty($contactsToAdd) && empty($contactsToRemove)) {\n return;\n }\n\n $this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);\n\n $this->removeContactAssociations($opportunity, $contactsToRemove);\n $this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);\n }\n\n private function getCurrentContactCrmIds(Opportunity $opportunity): array\n {\n return $opportunity->contacts()\n ->pluck('contacts.crm_provider_id')\n ->toArray();\n }\n\n private function logContactAssociationChanges(\n Opportunity $opportunity,\n array $currentContactCrmIds,\n array $contactAssociations,\n array $contactsToAdd,\n array $contactsToRemove\n ): void {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [\n 'opportunity_id' => $opportunity->getId(),\n 'current_contacts' => $currentContactCrmIds,\n 'new_contacts' => $contactAssociations,\n 'contacts_to_add' => $contactsToAdd,\n 'contacts_to_remove' => $contactsToRemove,\n ]);\n }\n\n private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void\n {\n if (empty($contactsToRemove)) {\n return;\n }\n\n $contactsToDetach = $opportunity->contacts()\n ->whereIn('contacts.crm_provider_id', $contactsToRemove)\n ->pluck('contacts.id')\n ->toArray();\n\n if (! empty($contactsToDetach)) {\n $opportunity->contacts()->detach($contactsToDetach);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_contact_crm_ids' => $contactsToRemove,\n 'removed_contact_count' => count($contactsToDetach),\n ]);\n }\n }\n\n private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void\n {\n if (empty($contactsToAdd)) {\n return;\n }\n\n $contactsAdded = [];\n foreach ($contactsToAdd as $crmId) {\n $id = $contactAssociations[$crmId];\n\n if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {\n $contactsAdded[] = $crmId;\n }\n }\n\n $this->logAddedContacts($opportunity, $contactsAdded);\n }\n\n private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool\n {\n try {\n $contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);\n\n if (! $contact) {\n return false;\n }\n\n return $this->performContactAttachment($opportunity, $contact, $crmId);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [\n 'opportunity_id' => $opportunity->getId(),\n 'contact_crm_id' => $crmId,\n 'error' => $e->getMessage(),\n ]);\n\n return false;\n }\n }\n\n private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool\n {\n try {\n $opportunity->contacts()->attach($contact->getId(), [\n 'crm_provider_id' => $crmId,\n ]);\n\n return true;\n } catch (\\Illuminate\\Database\\QueryException $e) {\n if (str_contains($e->getMessage(), 'Duplicate entry')) {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [\n 'contact_id' => $contact->getId(),\n 'contact_crm_id' => $crmId,\n 'opportunity_id' => $opportunity->getId(),\n ]);\n\n return false;\n }\n\n throw $e;\n }\n }\n\n private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void\n {\n if (! empty($contactsAdded)) {\n $this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'contacts_to_add_count' => count($contactsAdded),\n 'added_contact_crm_ids' => $contactsAdded,\n 'added_contacts_count' => count($contactsAdded),\n ]);\n }\n }\n}","depth":4,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\CollectionResponseAssociatedId;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\Account;\nuse Exception;\nuse Jiminny\\Component\\DealInsights\\Forecast\\Forecast;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Models\\Opportunity;\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Repositories\\Crm\\CrmEntityRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DealFieldsService;\nuse Jiminny\\Services\\Crm\\Hubspot\\OpportunitySyncStrategy\\HubspotSingleSyncStrategy;\nuse Jiminny\\Services\\Crm\\Hubspot\\WebhookSyncBatchProcessor;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Utils\\CurrencyFormatter;\n\n/**\n * Optimized sync methods for better performance\n * These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains\n */\ntrait OpportunitySyncTrait\n{\n private const int BATCH_SIZE = 100;\n private const int BATCH_PROCESS_SIZE = 800;\n\n protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n protected CrmEntityRepository $crmEntityRepository;\n protected DealFieldsService $dealFieldsService;\n\n private ?array $cachedClosedDealStages = null;\n private array $cachedBusinessProcesses = [];\n private array $cachedStages = [];\n\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n $parameters['config'] = $this->config;\n $syncCount = 0;\n $reportedTotal = 0;\n $lastSyncedId = [];\n\n try {\n foreach ($strategies as $strategyName => $syncStrategy) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .\n $strategyName\n );\n\n $total = 0;\n $lastId = null;\n $buffer = [];\n\n // HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies\n foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {\n $buffer[] = $hsOpportunity;\n\n // process every 800 rows (fits < 1 000 association limit)\n if (\\count($buffer) >= self::BATCH_PROCESS_SIZE) {\n $syncCount += $this->processOpportunityBatch($buffer);\n $buffer = [];\n }\n }\n\n // leftovers\n if ($buffer) {\n $syncCount += $this->processOpportunityBatch($buffer);\n }\n\n $reportedTotal += $total;\n $lastSyncedId = $lastId;\n }\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException | CrmException $e) {\n $this->handleSyncException($e, $parameters);\n }\n\n $this->logger->info(\n '[HubSpot] Synced opportunities',\n [\n 'team' => $this->team->getId(),\n 'sync_count' => $syncCount,\n 'total' => $reportedTotal,\n 'last_synced_id' => $lastSyncedId,\n ]\n );\n\n return $reportedTotal;\n }\n\n private function handleSyncException(\\Throwable $e, array $parameters): void\n {\n if (($parameters['since'] ?? null) instanceof Carbon) {\n $parameters['since'] = $parameters['since']->toDateTimeString();\n }\n $parameters['config'] = $this->config->getId();\n\n $this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [\n 'teamId' => $this->team->getUuid(),\n 'parameters' => $parameters,\n 'reason' => $e->getMessage(),\n ]);\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,\n );\n\n $parameters = [\n 'config' => $this->config,\n 'crm_id' => $crmId,\n ];\n\n try {\n if (! $strategy instanceof HubspotSingleSyncStrategy) {\n throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');\n }\n\n $hsOpportunity = $strategy->fetchOpportunity($parameters);\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->getUuid(),\n 'crmId' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);\n\n return $this->importOrUpdateOpportunity($hsOpportunity);\n }\n\n /**\n * Process webhook-collected opportunity batches.\n *\n * Drains Redis sets containing company CRM IDs collected from webhook events\n * and dispatches ImportOpportunityBatch jobs for batch processing.\n *\n * @return int Number of opportunity IDs dispatched to jobs\n */\n public function batchSyncOpportunities(): int\n {\n $configId = $this->team->getCrmConfiguration()->getId();\n\n return $this->batchProcessor->processBatchesForObjectType(\n WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,\n $configId\n );\n }\n\n /**\n * Import a batch of opportunities by their CRM IDs.\n * Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().\n *\n * @param array<string> $crmIds HubSpot deal CRM IDs\n *\n * @return array{success: array, failed_ids: array, errors?: array<string, string>}\n */\n public function importOpportunityBatchByIds(array $crmIds): array\n {\n $fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);\n\n $allDeals = [];\n foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {\n $deals = $this->client->getOpportunitiesByIds($chunk, $fields);\n foreach ($deals as $deal) {\n $allDeals[] = $deal;\n }\n }\n\n // IDs not returned by HubSpot are likely deleted or inaccessible deals.\n // These are not failures — retrying won't bring them back.\n $fetchedIds = array_map('strval', array_column($allDeals, 'id'));\n $notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));\n\n if (! empty($notFoundIds)) {\n $this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [\n 'teamId' => $this->team->getId(),\n 'notFoundCount' => \\count($notFoundIds),\n 'notFoundIds' => $notFoundIds,\n 'requestedCount' => \\count($crmIds),\n 'fetchedCount' => \\count($allDeals),\n ]);\n }\n\n if (empty($allDeals)) {\n return ['success' => [], 'failed_ids' => []];\n }\n\n return $this->importOpportunityBatch($allDeals);\n }\n\n private function getClosedDealStages(): array\n {\n if ($this->cachedClosedDealStages !== null) {\n return $this->cachedClosedDealStages;\n }\n\n $stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);\n $data = [\n 'lost' => [],\n 'won' => [],\n ];\n\n foreach ($stages as $stage) {\n if ($stage->probability == 0.00) {\n $data['lost'][] = $stage->crm_provider_id;\n }\n if ($stage->probability == 100.00) {\n $data['won'][] = $stage->crm_provider_id;\n }\n }\n\n $this->cachedClosedDealStages = $data;\n\n return $data;\n }\n\n /**\n * Import deals into the database with pre-fetched associations.\n *\n * API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT\n * caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()\n * where Laravel retries the whole job with backoff. After all retries exhausted,\n * failed() requeues all IDs to Redis.\n *\n * The per-deal loop catches exceptions individually. A deal can end up in three states:\n * - success: imported/updated successfully\n * - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)\n * These are permanent issues — retrying won't fix them.\n * - skipped (null): missing dependencies (no account, unknown pipeline/stage).\n * This is acceptable — the deal cannot be imported until those exist.\n */\n private function importOpportunityBatch(array $deals): array\n {\n $syncedOpportunities = [\n 'success' => [],\n 'failed_ids' => [],\n ];\n $dealIds = array_column($deals, 'id');\n\n // Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the\n // queue job retries the whole batch and eventually requeues all deal IDs back to Redis.\n try {\n $companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');\n $contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');\n\n $associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);\n\n $existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(\n $this->config,\n array_map('strval', $dealIds)\n );\n $existingCrmIdSet = array_flip($existingCrmIds);\n } catch (\\Throwable $e) {\n $this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [\n 'teamId' => $this->team->getId(),\n 'dealCount' => count($dealIds),\n 'error' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n foreach ($deals as $deal) {\n try {\n $deal['associations'] = $this->prepareAssociationsForOpportunity(\n $deal['id'],\n $companyAssociations,\n $contactAssociations,\n $associationsData\n );\n\n $syncedOpportunity = $this->importOrUpdateOpportunity(\n $deal,\n isset($existingCrmIdSet[(string) $deal['id']])\n );\n if ($syncedOpportunity) {\n $syncedOpportunities['success'][] = $syncedOpportunity;\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [\n 'teamId' => $this->team->getId(),\n 'crmId' => $deal['id'],\n 'error' => $e->getMessage(),\n ]);\n $syncedOpportunities['failed_ids'][] = $deal['id'];\n $syncedOpportunities['errors'][$deal['id']] = $e->getMessage();\n }\n }\n\n return $syncedOpportunities;\n }\n\n /**\n * Prepare associated entities for opportunities with optimized batch processing\n * Returns structured data with CRM ID to DB ID mappings for each opportunity\n */\n private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array\n {\n // Step 1: Collect all unique company and contact IDs from associations\n $allCompanyIds = $this->flattenAssociationIds($companyAssociations);\n $allContactIds = $this->flattenAssociationIds($contactAssociations);\n\n // Step 2: Batch sync missing entities and get CRM ID to DB ID mappings\n $companyIdMappings = [];\n $contactIdMappings = [];\n\n if (! empty($allCompanyIds)) {\n $companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);\n }\n\n if (! empty($allContactIds)) {\n $contactIdMappings = $this->prepareAssociatedContacts($allContactIds);\n }\n\n return [\n 'company_id_mappings' => $companyIdMappings,\n 'contact_id_mappings' => $contactIdMappings,\n ];\n }\n\n /**\n * Flatten association data to get unique IDs\n */\n private function flattenAssociationIds(array $associations): array\n {\n $ids = [];\n foreach ($associations as $dealAssociations) {\n if (is_array($dealAssociations)) {\n foreach ($dealAssociations as $id) {\n $ids[$id] = true;\n }\n }\n }\n\n return array_keys($ids);\n }\n\n /**\n * Batch sync missing accounts\n */\n private function prepareAssociatedAccounts(array $companyIds): array\n {\n // Find which accounts already exist\n $existingAccounts = $this->crmEntityRepository\n ->findAccountsByExternalIds($this->config, $companyIds);\n\n $existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();\n\n $existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {\n return [$account->getCrmProviderId() => $account->getId()];\n })->toArray();\n\n $missingCompanyIds = array_diff($companyIds, $existingCompanyIds);\n\n if (empty($missingCompanyIds)) {\n return $existingAccountsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [\n 'teamId' => $this->team->getUuid(),\n 'total_companies' => count($companyIds),\n 'existing_companies' => count($existingCompanyIds),\n 'missing_companies' => count($missingCompanyIds),\n ]);\n\n // we already have limit on opportunity ids count\n // Initialize variable before try block\n $syncedAccountsData = [];\n\n try {\n $syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [\n 'size' => count($missingCompanyIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedAccountsData = [];\n }\n\n return $existingAccountsData + $syncedAccountsData;\n }\n\n /**\n * Prepare associated contacts - find existing and sync missing ones\n * Returns mapping of CRM ID to DB ID\n */\n private function prepareAssociatedContacts(array $contactIds): array\n {\n // Find which contacts already exist\n $existingContacts = $this->crmEntityRepository\n ->findContactsByExternalIds($this->config, $contactIds);\n\n $existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();\n\n // Create mapping for existing contacts\n $existingContactsData = $existingContacts->mapWithKeys(function ($contact) {\n return [$contact->getCrmProviderId() => $contact->getId()];\n })->toArray();\n\n $missingContactIds = array_diff($contactIds, $existingContactIds);\n\n if (empty($missingContactIds)) {\n return $existingContactsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [\n 'teamId' => $this->team->getUuid(),\n 'total_contacts' => count($contactIds),\n 'existing_contacts' => count($existingContactIds),\n 'missing_contacts' => count($missingContactIds),\n ]);\n\n // Sync missing contacts using batch API\n try {\n $syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [\n 'size' => count($missingContactIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedContactsData = [];\n }\n\n return $existingContactsData + $syncedContactsData;\n }\n\n private function batchSyncCrmObjects(string $objectType, array $crmIds): array\n {\n $syncObjects = [];\n $crmObjectIds = array_values($crmIds);\n\n foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {\n try {\n $objects = $objectType === 'companies' ?\n $this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :\n $this->client->getContactsByIds($chunk, $this->getContactFields());\n\n foreach ($objects as $objectId => $objectData) {\n $this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [\n 'requested_count' => count($chunk),\n 'synced_count' => count($objects),\n ]);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [\n 'ids' => $chunk,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n return $syncObjects;\n }\n\n private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void\n {\n try {\n $object = $objectType === 'companies' ?\n $this->importAccount($objectData) :\n $this->importContact($objectData);\n\n if ($object) {\n $syncObjects[$object->getCrmProviderId()] = $object->getId();\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [\n 'id' => $objectId,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * Prepare associations for a single opportunity\n *\n * The return value is an array with the following structure:\n * [\n * 'companies' => [\n * $companyCrmId => $companyId,\n * ...\n * ],\n * 'contacts' => [\n * $contactCrmId => $contactId,\n * ...\n * ],\n * 'account_id' => $accountId,\n * ]\n */\n private function prepareAssociationsForOpportunity(\n string $oppCrmId,\n array $companyAssociations,\n array $contactAssociations,\n array $associationsData\n ): array {\n $associations = [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n\n $oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];\n foreach ($oppCompanyIds as $companyCrmId) {\n if (isset($associationsData['company_id_mappings'][$companyCrmId])) {\n $associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];\n\n // Set primary account (first company becomes primary account)\n if ($associations['account_id'] === null) {\n $associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];\n }\n }\n }\n\n $oppContactIds = $contactAssociations[$oppCrmId] ?? [];\n foreach ($oppContactIds as $contactCrmId) {\n if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {\n $associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];\n }\n }\n\n return $associations;\n }\n\n /**\n * Update only associations for an opportunity\n */\n private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void\n {\n // Update contact associations\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n // Update company (account) associations\n $this->updateOpportunityAccount($opportunity, $associations['account_id']);\n }\n\n /**\n * Remove all contact associations from an opportunity\n */\n private function removeAllOpportunityContacts(Opportunity $opportunity): void\n {\n $currentCount = (int) $opportunity->contacts()->count();\n\n if ($currentCount > 0) {\n $opportunity->contacts()->detach();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_count' => $currentCount,\n ]);\n }\n }\n\n private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void\n {\n if ($accountId === null) {\n // No account ID provided - keep current account\n return;\n }\n\n $currentAccountId = $opportunity->getAccountId();\n\n // Only update if account has changed\n if ($currentAccountId !== $accountId) {\n $opportunity->account_id = $accountId;\n $opportunity->save();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [\n 'opportunity_id' => $opportunity->getId(),\n 'old_account_id' => $currentAccountId,\n 'new_account_id' => $accountId,\n ]);\n }\n }\n\n /**\n * Find existing opportunities by external IDs (OPTIMIZED VERSION)\n * Uses batch query for better performance\n */\n private function findExistingOpportunities(array $crmIds): Collection\n {\n return $this->crmEntityRepository\n ->findOpportunitiesByExternalIds($this->config, $crmIds);\n }\n\n private function processOpportunityBatch(array $opportunities): int\n {\n $syncedOpportunities = $this->importOpportunityBatch($opportunities);\n\n return count($syncedOpportunities['success'] ?? []);\n }\n\n /**\n * Convert single deal associations from HubSpot format to internal format\n * Handles both HubSpot SDK objects and array formats\n *\n * @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed\n *\n * @return array Processed associations with DB IDs\n */\n private function convertDealAssociations(array $opportunityAssociations): array\n {\n $associations = $this->initializeAssociationsStructure();\n\n if (empty($opportunityAssociations)) {\n return $associations;\n }\n\n $associationIds = $this->extractAssociationIds($opportunityAssociations);\n\n $this->processCompanyAssociations($associationIds, $associations);\n $this->processContactAssociations($associationIds, $associations);\n\n return $associations;\n }\n\n private function initializeAssociationsStructure(): array\n {\n return [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n }\n\n private function extractAssociationIds(array $opportunityAssociations): array\n {\n $associationIds = [];\n\n foreach ($opportunityAssociations as $type => $associationData) {\n if (! empty($associationData)) {\n $associationIds[$type] = $this->convertSingleDealAssociations($associationData);\n }\n }\n\n return $associationIds;\n }\n\n private function processCompanyAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['companies'])) {\n return;\n }\n\n $companyId = $associationIds['companies'][0];\n $account = $this->findOrSyncAccount($companyId);\n\n if ($account instanceof Account) {\n $associations['companies'][$companyId] = $account->getId();\n $associations['account_id'] = $account->getId();\n }\n }\n\n private function processContactAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['contacts'])) {\n return;\n }\n\n foreach ($associationIds['contacts'] as $contactId) {\n $contact = $this->findOrSyncContact($contactId);\n\n if ($contact instanceof Contact) {\n $associations['contacts'][$contactId] = $contact->getId();\n }\n }\n }\n\n private function findOrSyncAccount(string $companyId): ?Account\n {\n $account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);\n\n if (! $account instanceof Account) {\n $account = $this->syncAccount($companyId);\n }\n\n return $account;\n }\n\n private function findOrSyncContact(string $contactId): ?Contact\n {\n $contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);\n\n if (! $contact instanceof Contact) {\n $contact = $this->syncContact($contactId);\n }\n\n return $contact;\n }\n\n private function convertSingleDealAssociations($opportunityAssociations = null): array\n {\n $associationData = [];\n\n if ($opportunityAssociations === null) {\n return $associationData;\n }\n\n // Handle array input (from extractAssociationIds)\n if (is_array($opportunityAssociations)) {\n return $opportunityAssociations;\n }\n\n // Handle CollectionResponseAssociatedId object\n if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {\n foreach ($opportunityAssociations->getResults() as $association) {\n $associationData[] = $association->getId();\n }\n }\n\n return $associationData;\n }\n\n private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity\n {\n if (empty($crmData['properties'])) {\n return null;\n }\n\n $crmId = (string) $crmData['id'];\n $properties = $crmData['properties'];\n $associations = $crmData['associations'] ?? [];\n\n $opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(\n $this->config,\n $crmId\n );\n\n if ($opportunityExists) {\n return $this->updateOpportunity($crmId, $properties, $associations);\n } else {\n return $this->createOpportunity($crmId, $properties, $associations);\n }\n }\n\n /**\n * Create new opportunity\n */\n private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n if (! $accountId) {\n return null;\n }\n\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n if (! $businessProcess) {\n return null;\n }\n\n $stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);\n if (! $stage) {\n return null;\n }\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n }\n\n /**\n * Update existing opportunity\n */\n private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n $stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->updateOpportunityAssociations($opportunity, $associations);\n\n return $opportunity;\n }\n\n private function resolveAccountId(array $associations): ?int\n {\n if (! empty($associations['accountId'])) {\n return $associations['accountId'];\n }\n\n if (empty($associations)) {\n return null;\n }\n\n // we can't resolve multiple account ids (currently SDK returns one company)\n foreach ($associations['companies'] as $accountId) {\n return $accountId;\n }\n\n return null;\n }\n\n private function buildOpportunityData(\n array $properties,\n ?int $accountId,\n ?BusinessProcess $businessProcess,\n ?Stage $stage\n ): array {\n $ownerId = null;\n $profile = null;\n if (! empty($properties['hubspot_owner_id'])) {\n $ownerId = $properties['hubspot_owner_id'];\n $profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);\n }\n\n $name = 'Unknown';\n if (isset($properties['dealname'])) {\n $name = mb_strimwidth($properties['dealname'], 0, 128);\n }\n\n $amount = $this->resolveAmount($properties);\n $currency = $properties['deal_currency_code'] ?? null;\n\n $closeDate = null;\n if (! empty($properties['closedate'])) {\n $closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');\n }\n\n $remotelyCreatedAt = null;\n if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {\n $date = $this->parseCleanDatetime($properties['createdate']);\n $remotelyCreatedAt = $date?->format('Y-m-d H:i:s');\n }\n\n $closedStages = $this->getClosedDealStages();\n $isWon = in_array($properties['dealstage'], $closedStages['won']);\n $isLost = in_array($properties['dealstage'], $closedStages['lost']);\n\n $data = [\n 'team_id' => $this->team->getId(),\n 'user_id' => $profile ? $profile->user_id : null,\n 'owner_id' => $ownerId,\n 'name' => $name,\n 'value' => ! empty($amount) ? $amount : null,\n 'currency_code' => CurrencyFormatter::formatCode($currency),\n 'close_date' => $closeDate,\n 'is_closed' => $isWon || $isLost,\n 'is_won' => $isWon,\n 'remotely_created_at' => $remotelyCreatedAt,\n 'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),\n 'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),\n ];\n\n if ($accountId) {\n $data['account_id'] = $accountId;\n }\n\n if ($stage) {\n $data['stage_id'] = $stage->id;\n }\n\n if ($businessProcess) {\n $recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);\n if ($recordType) {\n $data['record_type_id'] = $recordType->id;\n }\n }\n\n return $data;\n }\n\n private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess\n {\n if ($pipelineId === null) {\n return null;\n }\n\n if (isset($this->cachedBusinessProcesses[$pipelineId])) {\n return $this->cachedBusinessProcesses[$pipelineId];\n }\n\n $businessProcess = $this->getBusinessProcess($pipelineId);\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->importStages();\n $businessProcess = $this->getBusinessProcess($pipelineId);\n }\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->logger->info(\n '[HubSpot] Deal is not attached to a pipeline',\n [\n 'pipeline' => $pipelineId]\n );\n }\n\n $this->cachedBusinessProcesses[$pipelineId] = $businessProcess;\n\n return $businessProcess;\n }\n\n private function getBusinessProcess(string $pipelineId): ?BusinessProcess\n {\n return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);\n }\n\n private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage\n {\n if (empty($stageId)) {\n return null;\n }\n\n $cacheKey = $businessProcess->getId() . ':' . $stageId;\n if (isset($this->cachedStages[$cacheKey])) {\n return $this->cachedStages[$cacheKey];\n }\n\n $stage = $this->crmEntityRepository->getPipelineStageByConditions(\n $businessProcess,\n [\n 'crm_provider_id' => $stageId,\n 'type' => Stage::TYPE_OPPORTUNITY,\n ]\n );\n\n if ($stage === null) {\n $this->importStages(null, $stageId);\n }\n\n if ($stage === null) {\n $this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);\n }\n\n $this->cachedStages[$cacheKey] = $stage;\n\n return $stage;\n }\n\n private function resolveAmount(array $properties): ?string\n {\n $amount = null;\n if (! empty($properties['amount'])) {\n $amount = str_replace(',', '', $properties['amount']);\n }\n\n if ($this->config->hasDefaultCurrencyFieldSet()) {\n $valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();\n $amount = $properties[$valueFieldName] ?? $amount;\n }\n\n return $amount;\n }\n\n private function parseCleanDatetime(string $datetime): ?Carbon\n {\n // Treat pre-1980 values as invalid\n $minValidDate = Carbon::parse('1980-01-01 00:00:00');\n\n try {\n $date = Carbon::parse($datetime);\n\n if ($minValidDate->gt($date)) {\n return null;\n }\n\n return $date;\n } catch (Exception) {\n return null; // On parse error, treat as null\n }\n }\n\n private function resolveDealProbability(?string $stageProbability): int\n {\n if ($stageProbability === null) {\n return 0;\n }\n\n $probability = (float) $stageProbability;\n\n return $probability > 1 ? 0 : (int) ($probability * 100);\n }\n\n private function resolveForecastCategory(?string $forecastCategory): string\n {\n if (! $forecastCategory) {\n return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;\n }\n\n $forecastCategory = str_replace('_', ' ', $forecastCategory);\n\n return ucwords(strtolower($forecastCategory));\n }\n\n private function importExternalFieldData(array $properties, int $opportunityId): void\n {\n $crmFields = $this->getOpportunitySyncableFields();\n $this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);\n }\n\n private function importOpportunityContacts(Opportunity $opportunity, array $associations): void\n {\n // Handle empty or missing contact associations\n if (empty($associations)) {\n // Remove all existing contact associations if none provided\n $this->removeAllOpportunityContacts($opportunity);\n\n return;\n }\n\n // Use differential sync approach for better performance and accuracy\n $this->syncOpportunityContactsDifferential($opportunity, $associations);\n }\n\n /**\n * Sync opportunity contacts using differential approach\n * This compares current vs new associations and only makes necessary changes\n */\n private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void\n {\n $currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);\n $contactAssociationIds = array_keys($contactAssociations);\n\n $contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);\n $contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);\n\n if (empty($contactsToAdd) && empty($contactsToRemove)) {\n return;\n }\n\n $this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);\n\n $this->removeContactAssociations($opportunity, $contactsToRemove);\n $this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);\n }\n\n private function getCurrentContactCrmIds(Opportunity $opportunity): array\n {\n return $opportunity->contacts()\n ->pluck('contacts.crm_provider_id')\n ->toArray();\n }\n\n private function logContactAssociationChanges(\n Opportunity $opportunity,\n array $currentContactCrmIds,\n array $contactAssociations,\n array $contactsToAdd,\n array $contactsToRemove\n ): void {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [\n 'opportunity_id' => $opportunity->getId(),\n 'current_contacts' => $currentContactCrmIds,\n 'new_contacts' => $contactAssociations,\n 'contacts_to_add' => $contactsToAdd,\n 'contacts_to_remove' => $contactsToRemove,\n ]);\n }\n\n private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void\n {\n if (empty($contactsToRemove)) {\n return;\n }\n\n $contactsToDetach = $opportunity->contacts()\n ->whereIn('contacts.crm_provider_id', $contactsToRemove)\n ->pluck('contacts.id')\n ->toArray();\n\n if (! empty($contactsToDetach)) {\n $opportunity->contacts()->detach($contactsToDetach);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_contact_crm_ids' => $contactsToRemove,\n 'removed_contact_count' => count($contactsToDetach),\n ]);\n }\n }\n\n private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void\n {\n if (empty($contactsToAdd)) {\n return;\n }\n\n $contactsAdded = [];\n foreach ($contactsToAdd as $crmId) {\n $id = $contactAssociations[$crmId];\n\n if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {\n $contactsAdded[] = $crmId;\n }\n }\n\n $this->logAddedContacts($opportunity, $contactsAdded);\n }\n\n private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool\n {\n try {\n $contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);\n\n if (! $contact) {\n return false;\n }\n\n return $this->performContactAttachment($opportunity, $contact, $crmId);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [\n 'opportunity_id' => $opportunity->getId(),\n 'contact_crm_id' => $crmId,\n 'error' => $e->getMessage(),\n ]);\n\n return false;\n }\n }\n\n private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool\n {\n try {\n $opportunity->contacts()->attach($contact->getId(), [\n 'crm_provider_id' => $crmId,\n ]);\n\n return true;\n } catch (\\Illuminate\\Database\\QueryException $e) {\n if (str_contains($e->getMessage(), 'Duplicate entry')) {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [\n 'contact_id' => $contact->getId(),\n 'contact_crm_id' => $crmId,\n 'opportunity_id' => $opportunity->getId(),\n ]);\n\n return false;\n }\n\n throw $e;\n }\n }\n\n private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void\n {\n if (! empty($contactsAdded)) {\n $this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'contacts_to_add_count' => count($contactsAdded),\n 'added_contact_crm_ids' => $contactsAdded,\n 'added_contacts_count' => count($contactsAdded),\n ]);\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<template>\n <WelcomeLayout\n title=\"Account disconnected\"\n textPosition=\"center\"\n :icon=\"faUnlink\"\n :class=\"$style.layout\"\n >\n <div :class=\"$style.container\" v-if=\"providersLoaded\">\n <p>\n <strong>\n It looks like your {{ localProvider.displayName }} account has become\n disconnected\n </strong>\n </p>\n <p :class=\"$style.small\">Please re-connect to continue</p>\n <p v-if=\"isInIframe\">\n We'll open the {{ localProvider.displayName }} authentication in a new\n tab. Please return here and refresh the page once complete\n </p>\n\n <GoogleLikeButton\n v-if=\"localProvider.viaIntegrationApp && crmTokenLoaded\"\n as=\"a\"\n :key=\"localProvider.name\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n @click=\"integrationAppOnClick\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n <GoogleLikeButton\n v-if=\"!localProvider.viaIntegrationApp\"\n as=\"a\"\n :key=\"localProvider.name\"\n :href=\"`/auth/redirect/${localProvider.name}`\"\n :target=\"target\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n </div>\n <BuildInfo />\n\n <KioskBanner />\n </WelcomeLayout>\n</template>\n\n<script>\nimport window from \"window\";\nimport axios from \"axios\";\nimport { faUnlink } from \"@fortawesome/pro-regular-svg-icons\";\nimport isInIframe from \"@/utils/isInIframe\";\nimport BuildInfo from \"@/components/layout/BuildInfo/BuildInfo.vue\";\nimport KioskBanner from \"@/components/shared/KioskBanner/KioskBanner.vue\";\nimport WelcomeLayout from \"@/components/layout/WelcomeLayout/WelcomeLayout.vue\";\nimport GoogleLikeButton from \"@/components/shared/Buttons/GoogleLikeButton.vue\";\nimport { showSnackbarError, normalizeError } from \"@/utils/index\";\nimport { IntegrationAppClient } from \"@integration-app/sdk\";\n\nexport default {\n name: \"ConnectPage\",\n components: {\n BuildInfo,\n KioskBanner,\n WelcomeLayout,\n GoogleLikeButton,\n },\n data() {\n return {\n ...window.connectData,\n crmToken: null,\n faUnlink,\n isInIframe,\n providers: [],\n providersLoaded: false,\n crmTokenLoaded: false,\n };\n },\n computed: {\n localProvider() {\n return this.providers.find((e) => e.name === this.provider);\n },\n target() {\n return this.isInIframe ? \"_blank\" : null;\n },\n },\n created() {\n this.getProviders();\n },\n mounted() {\n this.showErrors();\n },\n watch: {\n providersLoaded() {\n if (this.providersLoaded) {\n this.prepareIntegrationAppConnection();\n }\n },\n },\n methods: {\n showErrors() {\n if (!this.error) return;\n\n showSnackbarError(this.error, undefined, undefined, false);\n },\n unwrapEntityResponse({ data }) {\n return data.map(({ icon, name, displayName, viaIntegrationApp }) => {\n return { icon, name, displayName, viaIntegrationApp };\n });\n },\n async getProviders() {\n try {\n const response = await axios.get(\"/api/v1/connect-providers\");\n this.providers = this.unwrapEntityResponse(response);\n this.providersLoaded = true;\n } catch {\n showSnackbarError(\n \"An error occurred, while loading form data (connect providers).\",\n );\n }\n },\n async prepareIntegrationAppConnection() {\n if (this.localProvider.viaIntegrationApp) {\n try {\n const response = await axios.get(\"/api/v1/integration-app-token\");\n this.crmToken = response.data.token;\n this.crmTokenLoaded = true;\n } catch (error) {\n console.log(error);\n showSnackbarError(\n `An error occurred while preparing the page.\n Try refreshing, if the error persists get in touch with the Jiminny team.`,\n );\n }\n }\n },\n async integrationAppOnClick() {\n console.log('[IntegrationApp] integrationAppOnClick called');\n const integrationApp = new IntegrationAppClient({\n token: this.crmToken,\n });\n\n const connection = await integrationApp\n .integration(this.localProvider.name)\n .openNewConnection({\n showPoweredBy: false,\n allowMultipleConnections: false,\n }).catch((err) => {\n console.log('[IntegrationApp] openNewConnection rejected:', err);\n return null;\n });\n\n console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));\n\n // [IntegrationApp] openNewConnection resolved: {\n // \"id\":\"69e0b41a67d0068c2ca0b48e\",\n // \"name\":\"Zoho CRM\",\n // \"userId\":\"1ece66c8-feb1-4df1-b321-21607daf4623\",\n // \"tenantId\":\"69e0b3faef3e7b6248189289\",\n // \"isTest\":false,\n // \"connected\":true,\n // \"state\":\"READY\",\n // \"errors\":[],\n // \"integrationId\":\"66fe6c913202f3a165e3c14d\",\n // \"externalAppId\":\"6671653e7e2d642e4e41b0fa\",\n // \"authOptionKey\":\"\",\n // \"createdAt\":\"2026-04-16T10:04:10.420Z\",\n // \"updatedAt\":\"2026-04-16T10:04:10.575Z\",\n // \"retryAttempts\":0,\n // \"isDeactivated\":false\n // }\n\n if (connection && connection.disconnected !== true && connection.connected !== false) {\n console.log('[IntegrationApp] connection condition matched');\n try {\n const saveRequest = await axios.post(\n \"/api/v1/integration-app-connect\",\n );\n if (saveRequest.data && saveRequest.data.success === true) {\n /** If all is good refresh the page here */\n window.location = \"/dashboard\";\n return;\n }\n\n throw new Error(saveRequest.data.message);\n } catch (error) {\n console.log(error);\n showSnackbarError(normalizeError(error));\n }\n }\n },\n },\n};\n</script>\n\n<style module lang=\"less\" src=\"./connect.less\"></style>","depth":4,"value":"<template>\n <WelcomeLayout\n title=\"Account disconnected\"\n textPosition=\"center\"\n :icon=\"faUnlink\"\n :class=\"$style.layout\"\n >\n <div :class=\"$style.container\" v-if=\"providersLoaded\">\n <p>\n <strong>\n It looks like your {{ localProvider.displayName }} account has become\n disconnected\n </strong>\n </p>\n <p :class=\"$style.small\">Please re-connect to continue</p>\n <p v-if=\"isInIframe\">\n We'll open the {{ localProvider.displayName }} authentication in a new\n tab. Please return here and refresh the page once complete\n </p>\n\n <GoogleLikeButton\n v-if=\"localProvider.viaIntegrationApp && crmTokenLoaded\"\n as=\"a\"\n :key=\"localProvider.name\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n @click=\"integrationAppOnClick\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n <GoogleLikeButton\n v-if=\"!localProvider.viaIntegrationApp\"\n as=\"a\"\n :key=\"localProvider.name\"\n :href=\"`/auth/redirect/${localProvider.name}`\"\n :target=\"target\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n </div>\n <BuildInfo />\n\n <KioskBanner />\n </WelcomeLayout>\n</template>\n\n<script>\nimport window from \"window\";\nimport axios from \"axios\";\nimport { faUnlink } from \"@fortawesome/pro-regular-svg-icons\";\nimport isInIframe from \"@/utils/isInIframe\";\nimport BuildInfo from \"@/components/layout/BuildInfo/BuildInfo.vue\";\nimport KioskBanner from \"@/components/shared/KioskBanner/KioskBanner.vue\";\nimport WelcomeLayout from \"@/components/layout/WelcomeLayout/WelcomeLayout.vue\";\nimport GoogleLikeButton from \"@/components/shared/Buttons/GoogleLikeButton.vue\";\nimport { showSnackbarError, normalizeError } from \"@/utils/index\";\nimport { IntegrationAppClient } from \"@integration-app/sdk\";\n\nexport default {\n name: \"ConnectPage\",\n components: {\n BuildInfo,\n KioskBanner,\n WelcomeLayout,\n GoogleLikeButton,\n },\n data() {\n return {\n ...window.connectData,\n crmToken: null,\n faUnlink,\n isInIframe,\n providers: [],\n providersLoaded: false,\n crmTokenLoaded: false,\n };\n },\n computed: {\n localProvider() {\n return this.providers.find((e) => e.name === this.provider);\n },\n target() {\n return this.isInIframe ? \"_blank\" : null;\n },\n },\n created() {\n this.getProviders();\n },\n mounted() {\n this.showErrors();\n },\n watch: {\n providersLoaded() {\n if (this.providersLoaded) {\n this.prepareIntegrationAppConnection();\n }\n },\n },\n methods: {\n showErrors() {\n if (!this.error) return;\n\n showSnackbarError(this.error, undefined, undefined, false);\n },\n unwrapEntityResponse({ data }) {\n return data.map(({ icon, name, displayName, viaIntegrationApp }) => {\n return { icon, name, displayName, viaIntegrationApp };\n });\n },\n async getProviders() {\n try {\n const response = await axios.get(\"/api/v1/connect-providers\");\n this.providers = this.unwrapEntityResponse(response);\n this.providersLoaded = true;\n } catch {\n showSnackbarError(\n \"An error occurred, while loading form data (connect providers).\",\n );\n }\n },\n async prepareIntegrationAppConnection() {\n if (this.localProvider.viaIntegrationApp) {\n try {\n const response = await axios.get(\"/api/v1/integration-app-token\");\n this.crmToken = response.data.token;\n this.crmTokenLoaded = true;\n } catch (error) {\n console.log(error);\n showSnackbarError(\n `An error occurred while preparing the page.\n Try refreshing, if the error persists get in touch with the Jiminny team.`,\n );\n }\n }\n },\n async integrationAppOnClick() {\n console.log('[IntegrationApp] integrationAppOnClick called');\n const integrationApp = new IntegrationAppClient({\n token: this.crmToken,\n });\n\n const connection = await integrationApp\n .integration(this.localProvider.name)\n .openNewConnection({\n showPoweredBy: false,\n allowMultipleConnections: false,\n }).catch((err) => {\n console.log('[IntegrationApp] openNewConnection rejected:', err);\n return null;\n });\n\n console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));\n\n // [IntegrationApp] openNewConnection resolved: {\n // \"id\":\"69e0b41a67d0068c2ca0b48e\",\n // \"name\":\"Zoho CRM\",\n // \"userId\":\"1ece66c8-feb1-4df1-b321-21607daf4623\",\n // \"tenantId\":\"69e0b3faef3e7b6248189289\",\n // \"isTest\":false,\n // \"connected\":true,\n // \"state\":\"READY\",\n // \"errors\":[],\n // \"integrationId\":\"66fe6c913202f3a165e3c14d\",\n // \"externalAppId\":\"6671653e7e2d642e4e41b0fa\",\n // \"authOptionKey\":\"\",\n // \"createdAt\":\"2026-04-16T10:04:10.420Z\",\n // \"updatedAt\":\"2026-04-16T10:04:10.575Z\",\n // \"retryAttempts\":0,\n // \"isDeactivated\":false\n // }\n\n if (connection && connection.disconnected !== true && connection.connected !== false) {\n console.log('[IntegrationApp] connection condition matched');\n try {\n const saveRequest = await axios.post(\n \"/api/v1/integration-app-connect\",\n );\n if (saveRequest.data && saveRequest.data.success === true) {\n /** If all is good refresh the page here */\n window.location = \"/dashboard\";\n return;\n }\n\n throw new Error(saveRequest.data.message);\n } catch (error) {\n console.log(error);\n showSnackbarError(normalizeError(error));\n }\n }\n },\n },\n};\n</script>\n\n<style module lang=\"less\" src=\"./connect.less\"></style>","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-9063734413195222639
|
-8178086449155632858
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Code changed:
Hide
Sync Changes
Hide This Notification
33
2
19
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use HubSpot\Client\Crm\Deals\Model\CollectionResponseAssociatedId;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\Account;
use Exception;
use Jiminny\Component\DealInsights\Forecast\Forecast;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Contact;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Exceptions\CrmException;
use Jiminny\Models\Opportunity;
use Illuminate\Support\Collection;
use Jiminny\Models\Stage;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Services\Crm\Hubspot\DealFieldsService;
use Jiminny\Services\Crm\Hubspot\OpportunitySyncStrategy\HubspotSingleSyncStrategy;
use Jiminny\Services\Crm\Hubspot\WebhookSyncBatchProcessor;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Utils\CurrencyFormatter;
/**
* Optimized sync methods for better performance
* These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains
*/
trait OpportunitySyncTrait
{
private const int BATCH_SIZE = 100;
private const int BATCH_PROCESS_SIZE = 800;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected DealFieldsService $dealFieldsService;
private ?array $cachedClosedDealStages = null;
private array $cachedBusinessProcesses = [];
private array $cachedStages = [];
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$parameters['config'] = $this->config;
$syncCount = 0;
$reportedTotal = 0;
$lastSyncedId = [];
try {
foreach ($strategies as $strategyName => $syncStrategy) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .
$strategyName
);
$total = 0;
$lastId = null;
$buffer = [];
// HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies
foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {
$buffer[] = $hsOpportunity;
// process every 800 rows (fits < 1 000 association limit)
if (\count($buffer) >= self::BATCH_PROCESS_SIZE) {
$syncCount += $this->processOpportunityBatch($buffer);
$buffer = [];
}
}
// leftovers
if ($buffer) {
$syncCount += $this->processOpportunityBatch($buffer);
}
$reportedTotal += $total;
$lastSyncedId = $lastId;
}
} catch (\HubSpot\Client\Crm\Deals\ApiException | CrmException $e) {
$this->handleSyncException($e, $parameters);
}
$this->logger->info(
'[HubSpot] Synced opportunities',
[
'team' => $this->team->getId(),
'sync_count' => $syncCount,
'total' => $reportedTotal,
'last_synced_id' => $lastSyncedId,
]
);
return $reportedTotal;
}
private function handleSyncException(\Throwable $e, array $parameters): void
{
if (($parameters['since'] ?? null) instanceof Carbon) {
$parameters['since'] = $parameters['since']->toDateTimeString();
}
$parameters['config'] = $this->config->getId();
$this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [
'teamId' => $this->team->getUuid(),
'parameters' => $parameters,
'reason' => $e->getMessage(),
]);
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,
);
$parameters = [
'config' => $this->config,
'crm_id' => $crmId,
];
try {
if (! $strategy instanceof HubspotSingleSyncStrategy) {
throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');
}
$hsOpportunity = $strategy->fetchOpportunity($parameters);
} catch (\HubSpot\Client\Crm\Deals\ApiException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->getUuid(),
'crmId' => $crmId,
'reason' => $e->getMessage(),
]);
return null;
}
$hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);
return $this->importOrUpdateOpportunity($hsOpportunity);
}
/**
* Process webhook-collected opportunity batches.
*
* Drains Redis sets containing company CRM IDs collected from webhook events
* and dispatches ImportOpportunityBatch jobs for batch processing.
*
* @return int Number of opportunity IDs dispatched to jobs
*/
public function batchSyncOpportunities(): int
{
$configId = $this->team->getCrmConfiguration()->getId();
return $this->batchProcessor->processBatchesForObjectType(
WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,
$configId
);
}
/**
* Import a batch of opportunities by their CRM IDs.
* Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().
*
* @param array<string> $crmIds HubSpot deal CRM IDs
*
* @return array{success: array, failed_ids: array, errors?: array<string, string>}
*/
public function importOpportunityBatchByIds(array $crmIds): array
{
$fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);
$allDeals = [];
foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {
$deals = $this->client->getOpportunitiesByIds($chunk, $fields);
foreach ($deals as $deal) {
$allDeals[] = $deal;
}
}
// IDs not returned by HubSpot are likely deleted or inaccessible deals.
// These are not failures — retrying won't bring them back.
$fetchedIds = array_map('strval', array_column($allDeals, 'id'));
$notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));
if (! empty($notFoundIds)) {
$this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [
'teamId' => $this->team->getId(),
'notFoundCount' => \count($notFoundIds),
'notFoundIds' => $notFoundIds,
'requestedCount' => \count($crmIds),
'fetchedCount' => \count($allDeals),
]);
}
if (empty($allDeals)) {
return ['success' => [], 'failed_ids' => []];
}
return $this->importOpportunityBatch($allDeals);
}
private function getClosedDealStages(): array
{
if ($this->cachedClosedDealStages !== null) {
return $this->cachedClosedDealStages;
}
$stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);
$data = [
'lost' => [],
'won' => [],
];
foreach ($stages as $stage) {
if ($stage->probability == 0.00) {
$data['lost'][] = $stage->crm_provider_id;
}
if ($stage->probability == 100.00) {
$data['won'][] = $stage->crm_provider_id;
}
}
$this->cachedClosedDealStages = $data;
return $data;
}
/**
* Import deals into the database with pre-fetched associations.
*
* API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT
* caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()
* where Laravel retries the whole job with backoff. After all retries exhausted,
* failed() requeues all IDs to Redis.
*
* The per-deal loop catches exceptions individually. A deal can end up in three states:
* - success: imported/updated successfully
* - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)
* These are permanent issues — retrying won't fix them.
* - skipped (null): missing dependencies (no account, unknown pipeline/stage).
* This is acceptable — the deal cannot be imported until those exist.
*/
private function importOpportunityBatch(array $deals): array
{
$syncedOpportunities = [
'success' => [],
'failed_ids' => [],
];
$dealIds = array_column($deals, 'id');
// Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the
// queue job retries the whole batch and eventually requeues all deal IDs back to Redis.
try {
$companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');
$contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');
$associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);
$existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(
$this->config,
array_map('strval', $dealIds)
);
$existingCrmIdSet = array_flip($existingCrmIds);
} catch (\Throwable $e) {
$this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [
'teamId' => $this->team->getId(),
'dealCount' => count($dealIds),
'error' => $e->getMessage(),
]);
throw $e;
}
foreach ($deals as $deal) {
try {
$deal['associations'] = $this->prepareAssociationsForOpportunity(
$deal['id'],
$companyAssociations,
$contactAssociations,
$associationsData
);
$syncedOpportunity = $this->importOrUpdateOpportunity(
$deal,
isset($existingCrmIdSet[(string) $deal['id']])
);
if ($syncedOpportunity) {
$syncedOpportunities['success'][] = $syncedOpportunity;
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [
'teamId' => $this->team->getId(),
'crmId' => $deal['id'],
'error' => $e->getMessage(),
]);
$syncedOpportunities['failed_ids'][] = $deal['id'];
$syncedOpportunities['errors'][$deal['id']] = $e->getMessage();
}
}
return $syncedOpportunities;
}
/**
* Prepare associated entities for opportunities with optimized batch processing
* Returns structured data with CRM ID to DB ID mappings for each opportunity
*/
private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array
{
// Step 1: Collect all unique company and contact IDs from associations
$allCompanyIds = $this->flattenAssociationIds($companyAssociations);
$allContactIds = $this->flattenAssociationIds($contactAssociations);
// Step 2: Batch sync missing entities and get CRM ID to DB ID mappings
$companyIdMappings = [];
$contactIdMappings = [];
if (! empty($allCompanyIds)) {
$companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);
}
if (! empty($allContactIds)) {
$contactIdMappings = $this->prepareAssociatedContacts($allContactIds);
}
return [
'company_id_mappings' => $companyIdMappings,
'contact_id_mappings' => $contactIdMappings,
];
}
/**
* Flatten association data to get unique IDs
*/
private function flattenAssociationIds(array $associations): array
{
$ids = [];
foreach ($associations as $dealAssociations) {
if (is_array($dealAssociations)) {
foreach ($dealAssociations as $id) {
$ids[$id] = true;
}
}
}
return array_keys($ids);
}
/**
* Batch sync missing accounts
*/
private function prepareAssociatedAccounts(array $companyIds): array
{
// Find which accounts already exist
$existingAccounts = $this->crmEntityRepository
->findAccountsByExternalIds($this->config, $companyIds);
$existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();
$existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {
return [$account->getCrmProviderId() => $account->getId()];
})->toArray();
$missingCompanyIds = array_diff($companyIds, $existingCompanyIds);
if (empty($missingCompanyIds)) {
return $existingAccountsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [
'teamId' => $this->team->getUuid(),
'total_companies' => count($companyIds),
'existing_companies' => count($existingCompanyIds),
'missing_companies' => count($missingCompanyIds),
]);
// we already have limit on opportunity ids count
// Initialize variable before try block
$syncedAccountsData = [];
try {
$syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [
'size' => count($missingCompanyIds),
'error' => $e->getMessage(),
]);
$syncedAccountsData = [];
}
return $existingAccountsData + $syncedAccountsData;
}
/**
* Prepare associated contacts - find existing and sync missing ones
* Returns mapping of CRM ID to DB ID
*/
private function prepareAssociatedContacts(array $contactIds): array
{
// Find which contacts already exist
$existingContacts = $this->crmEntityRepository
->findContactsByExternalIds($this->config, $contactIds);
$existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();
// Create mapping for existing contacts
$existingContactsData = $existingContacts->mapWithKeys(function ($contact) {
return [$contact->getCrmProviderId() => $contact->getId()];
})->toArray();
$missingContactIds = array_diff($contactIds, $existingContactIds);
if (empty($missingContactIds)) {
return $existingContactsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [
'teamId' => $this->team->getUuid(),
'total_contacts' => count($contactIds),
'existing_contacts' => count($existingContactIds),
'missing_contacts' => count($missingContactIds),
]);
// Sync missing contacts using batch API
try {
$syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [
'size' => count($missingContactIds),
'error' => $e->getMessage(),
]);
$syncedContactsData = [];
}
return $existingContactsData + $syncedContactsData;
}
private function batchSyncCrmObjects(string $objectType, array $crmIds): array
{
$syncObjects = [];
$crmObjectIds = array_values($crmIds);
foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {
try {
$objects = $objectType === 'companies' ?
$this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :
$this->client->getContactsByIds($chunk, $this->getContactFields());
foreach ($objects as $objectId => $objectData) {
$this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [
'requested_count' => count($chunk),
'synced_count' => count($objects),
]);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [
'ids' => $chunk,
'error' => $e->getMessage(),
]);
}
}
return $syncObjects;
}
private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void
{
try {
$object = $objectType === 'companies' ?
$this->importAccount($objectData) :
$this->importContact($objectData);
if ($object) {
$syncObjects[$object->getCrmProviderId()] = $object->getId();
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [
'id' => $objectId,
'error' => $e->getMessage(),
]);
}
}
/**
* Prepare associations for a single opportunity
*
* The return value is an array with the following structure:
* [
* 'companies' => [
* $companyCrmId => $companyId,
* ...
* ],
* 'contacts' => [
* $contactCrmId => $contactId,
* ...
* ],
* 'account_id' => $accountId,
* ]
*/
private function prepareAssociationsForOpportunity(
string $oppCrmId,
array $companyAssociations,
array $contactAssociations,
array $associationsData
): array {
$associations = [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
$oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];
foreach ($oppCompanyIds as $companyCrmId) {
if (isset($associationsData['company_id_mappings'][$companyCrmId])) {
$associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];
// Set primary account (first company becomes primary account)
if ($associations['account_id'] === null) {
$associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];
}
}
}
$oppContactIds = $contactAssociations[$oppCrmId] ?? [];
foreach ($oppContactIds as $contactCrmId) {
if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {
$associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];
}
}
return $associations;
}
/**
* Update only associations for an opportunity
*/
private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void
{
// Update contact associations
$this->importOpportunityContacts($opportunity, $associations['contacts']);
// Update company (account) associations
$this->updateOpportunityAccount($opportunity, $associations['account_id']);
}
/**
* Remove all contact associations from an opportunity
*/
private function removeAllOpportunityContacts(Opportunity $opportunity): void
{
$currentCount = (int) $opportunity->contacts()->count();
if ($currentCount > 0) {
$opportunity->contacts()->detach();
$this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_count' => $currentCount,
]);
}
}
private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void
{
if ($accountId === null) {
// No account ID provided - keep current account
return;
}
$currentAccountId = $opportunity->getAccountId();
// Only update if account has changed
if ($currentAccountId !== $accountId) {
$opportunity->account_id = $accountId;
$opportunity->save();
$this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [
'opportunity_id' => $opportunity->getId(),
'old_account_id' => $currentAccountId,
'new_account_id' => $accountId,
]);
}
}
/**
* Find existing opportunities by external IDs (OPTIMIZED VERSION)
* Uses batch query for better performance
*/
private function findExistingOpportunities(array $crmIds): Collection
{
return $this->crmEntityRepository
->findOpportunitiesByExternalIds($this->config, $crmIds);
}
private function processOpportunityBatch(array $opportunities): int
{
$syncedOpportunities = $this->importOpportunityBatch($opportunities);
return count($syncedOpportunities['success'] ?? []);
}
/**
* Convert single deal associations from HubSpot format to internal format
* Handles both HubSpot SDK objects and array formats
*
* @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed
*
* @return array Processed associations with DB IDs
*/
private function convertDealAssociations(array $opportunityAssociations): array
{
$associations = $this->initializeAssociationsStructure();
if (empty($opportunityAssociations)) {
return $associations;
}
$associationIds = $this->extractAssociationIds($opportunityAssociations);
$this->processCompanyAssociations($associationIds, $associations);
$this->processContactAssociations($associationIds, $associations);
return $associations;
}
private function initializeAssociationsStructure(): array
{
return [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
}
private function extractAssociationIds(array $opportunityAssociations): array
{
$associationIds = [];
foreach ($opportunityAssociations as $type => $associationData) {
if (! empty($associationData)) {
$associationIds[$type] = $this->convertSingleDealAssociations($associationData);
}
}
return $associationIds;
}
private function processCompanyAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['companies'])) {
return;
}
$companyId = $associationIds['companies'][0];
$account = $this->findOrSyncAccount($companyId);
if ($account instanceof Account) {
$associations['companies'][$companyId] = $account->getId();
$associations['account_id'] = $account->getId();
}
}
private function processContactAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['contacts'])) {
return;
}
foreach ($associationIds['contacts'] as $contactId) {
$contact = $this->findOrSyncContact($contactId);
if ($contact instanceof Contact) {
$associations['contacts'][$contactId] = $contact->getId();
}
}
}
private function findOrSyncAccount(string $companyId): ?Account
{
$account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);
if (! $account instanceof Account) {
$account = $this->syncAccount($companyId);
}
return $account;
}
private function findOrSyncContact(string $contactId): ?Contact
{
$contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);
if (! $contact instanceof Contact) {
$contact = $this->syncContact($contactId);
}
return $contact;
}
private function convertSingleDealAssociations($opportunityAssociations = null): array
{
$associationData = [];
if ($opportunityAssociations === null) {
return $associationData;
}
// Handle array input (from extractAssociationIds)
if (is_array($opportunityAssociations)) {
return $opportunityAssociations;
}
// Handle CollectionResponseAssociatedId object
if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {
foreach ($opportunityAssociations->getResults() as $association) {
$associationData[] = $association->getId();
}
}
return $associationData;
}
private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity
{
if (empty($crmData['properties'])) {
return null;
}
$crmId = (string) $crmData['id'];
$properties = $crmData['properties'];
$associations = $crmData['associations'] ?? [];
$opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(
$this->config,
$crmId
);
if ($opportunityExists) {
return $this->updateOpportunity($crmId, $properties, $associations);
} else {
return $this->createOpportunity($crmId, $properties, $associations);
}
}
/**
* Create new opportunity
*/
private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity
{
$accountId = $this->resolveAccountId($associations);
if (! $accountId) {
return null;
}
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
if (! $businessProcess) {
return null;
}
$stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);
if (! $stage) {
return null;
}
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->importOpportunityContacts($opportunity, $associations['contacts']);
if ($opportunity->wasRecentlyCreated) {
MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());
}
return $opportunity;
}
/**
* Update existing opportunity
*/
private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity
{
$accountId = $this->resolveAccountId($associations);
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
$stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->updateOpportunityAssociations($opportunity, $associations);
return $opportunity;
}
private function resolveAccountId(array $associations): ?int
{
if (! empty($associations['accountId'])) {
return $associations['accountId'];
}
if (empty($associations)) {
return null;
}
// we can't resolve multiple account ids (currently SDK returns one company)
foreach ($associations['companies'] as $accountId) {
return $accountId;
}
return null;
}
private function buildOpportunityData(
array $properties,
?int $accountId,
?BusinessProcess $businessProcess,
?Stage $stage
): array {
$ownerId = null;
$profile = null;
if (! empty($properties['hubspot_owner_id'])) {
$ownerId = $properties['hubspot_owner_id'];
$profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);
}
$name = 'Unknown';
if (isset($properties['dealname'])) {
$name = mb_strimwidth($properties['dealname'], 0, 128);
}
$amount = $this->resolveAmount($properties);
$currency = $properties['deal_currency_code'] ?? null;
$closeDate = null;
if (! empty($properties['closedate'])) {
$closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');
}
$remotelyCreatedAt = null;
if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {
$date = $this->parseCleanDatetime($properties['createdate']);
$remotelyCreatedAt = $date?->format('Y-m-d H:i:s');
}
$closedStages = $this->getClosedDealStages();
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$data = [
'team_id' => $this->team->getId(),
'user_id' => $profile ? $profile->user_id : null,
'owner_id' => $ownerId,
'name' => $name,
'value' => ! empty($amount) ? $amount : null,
'currency_code' => CurrencyFormatter::formatCode($currency),
'close_date' => $closeDate,
'is_closed' => $isWon || $isLost,
'is_won' => $isWon,
'remotely_created_at' => $remotelyCreatedAt,
'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),
'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),
];
if ($accountId) {
$data['account_id'] = $accountId;
}
if ($stage) {
$data['stage_id'] = $stage->id;
}
if ($businessProcess) {
$recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);
if ($recordType) {
$data['record_type_id'] = $recordType->id;
}
}
return $data;
}
private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess
{
if ($pipelineId === null) {
return null;
}
if (isset($this->cachedBusinessProcesses[$pipelineId])) {
return $this->cachedBusinessProcesses[$pipelineId];
}
$businessProcess = $this->getBusinessProcess($pipelineId);
if (! $businessProcess instanceof BusinessProcess) {
$this->importStages();
$businessProcess = $this->getBusinessProcess($pipelineId);
}
if (! $businessProcess instanceof BusinessProcess) {
$this->logger->info(
'[HubSpot] Deal is not attached to a pipeline',
[
'pipeline' => $pipelineId]
);
}
$this->cachedBusinessProcesses[$pipelineId] = $businessProcess;
return $businessProcess;
}
private function getBusinessProcess(string $pipelineId): ?BusinessProcess
{
return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);
}
private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage
{
if (empty($stageId)) {
return null;
}
$cacheKey = $businessProcess->getId() . ':' . $stageId;
if (isset($this->cachedStages[$cacheKey])) {
return $this->cachedStages[$cacheKey];
}
$stage = $this->crmEntityRepository->getPipelineStageByConditions(
$businessProcess,
[
'crm_provider_id' => $stageId,
'type' => Stage::TYPE_OPPORTUNITY,
]
);
if ($stage === null) {
$this->importStages(null, $stageId);
}
if ($stage === null) {
$this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);
}
$this->cachedStages[$cacheKey] = $stage;
return $stage;
}
private function resolveAmount(array $properties): ?string
{
$amount = null;
if (! empty($properties['amount'])) {
$amount = str_replace(',', '', $properties['amount']);
}
if ($this->config->hasDefaultCurrencyFieldSet()) {
$valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();
$amount = $properties[$valueFieldName] ?? $amount;
}
return $amount;
}
private function parseCleanDatetime(string $datetime): ?Carbon
{
// Treat pre-1980 values as invalid
$minValidDate = Carbon::parse('1980-01-01 00:00:00');
try {
$date = Carbon::parse($datetime);
if ($minValidDate->gt($date)) {
return null;
}
return $date;
} catch (Exception) {
return null; // On parse error, treat as null
}
}
private function resolveDealProbability(?string $stageProbability): int
{
if ($stageProbability === null) {
return 0;
}
$probability = (float) $stageProbability;
return $probability > 1 ? 0 : (int) ($probability * 100);
}
private function resolveForecastCategory(?string $forecastCategory): string
{
if (! $forecastCategory) {
return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;
}
$forecastCategory = str_replace('_', ' ', $forecastCategory);
return ucwords(strtolower($forecastCategory));
}
private function importExternalFieldData(array $properties, int $opportunityId): void
{
$crmFields = $this->getOpportunitySyncableFields();
$this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);
}
private function importOpportunityContacts(Opportunity $opportunity, array $associations): void
{
// Handle empty or missing contact associations
if (empty($associations)) {
// Remove all existing contact associations if none provided
$this->removeAllOpportunityContacts($opportunity);
return;
}
// Use differential sync approach for better performance and accuracy
$this->syncOpportunityContactsDifferential($opportunity, $associations);
}
/**
* Sync opportunity contacts using differential approach
* This compares current vs new associations and only makes necessary changes
*/
private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void
{
$currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);
$contactAssociationIds = array_keys($contactAssociations);
$contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);
$contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);
if (empty($contactsToAdd) && empty($contactsToRemove)) {
return;
}
$this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);
$this->removeContactAssociations($opportunity, $contactsToRemove);
$this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);
}
private function getCurrentContactCrmIds(Opportunity $opportunity): array
{
return $opportunity->contacts()
->pluck('contacts.crm_provider_id')
->toArray();
}
private function logContactAssociationChanges(
Opportunity $opportunity,
array $currentContactCrmIds,
array $contactAssociations,
array $contactsToAdd,
array $contactsToRemove
): void {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [
'opportunity_id' => $opportunity->getId(),
'current_contacts' => $currentContactCrmIds,
'new_contacts' => $contactAssociations,
'contacts_to_add' => $contactsToAdd,
'contacts_to_remove' => $contactsToRemove,
]);
}
private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void
{
if (empty($contactsToRemove)) {
return;
}
$contactsToDetach = $opportunity->contacts()
->whereIn('contacts.crm_provider_id', $contactsToRemove)
->pluck('contacts.id')
->toArray();
if (! empty($contactsToDetach)) {
$opportunity->contacts()->detach($contactsToDetach);
$this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_contact_crm_ids' => $contactsToRemove,
'removed_contact_count' => count($contactsToDetach),
]);
}
}
private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void
{
if (empty($contactsToAdd)) {
return;
}
$contactsAdded = [];
foreach ($contactsToAdd as $crmId) {
$id = $contactAssociations[$crmId];
if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {
$contactsAdded[] = $crmId;
}
}
$this->logAddedContacts($opportunity, $contactsAdded);
}
private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool
{
try {
$contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);
if (! $contact) {
return false;
}
return $this->performContactAttachment($opportunity, $contact, $crmId);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [
'opportunity_id' => $opportunity->getId(),
'contact_crm_id' => $crmId,
'error' => $e->getMessage(),
]);
return false;
}
}
private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool
{
try {
$opportunity->contacts()->attach($contact->getId(), [
'crm_provider_id' => $crmId,
]);
return true;
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [
'contact_id' => $contact->getId(),
'contact_crm_id' => $crmId,
'opportunity_id' => $opportunity->getId(),
]);
return false;
}
throw $e;
}
}
private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void
{
if (! empty($contactsAdded)) {
$this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [
'opportunity_id' => $opportunity->getId(),
'contacts_to_add_count' => count($contactsAdded),
'added_contact_crm_ids' => $contactsAdded,
'added_contacts_count' => count($contactsAdded),
]);
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<template>
<WelcomeLayout
title="Account disconnected"
textPosition="center"
:icon="faUnlink"
:class="$style.layout"
>
<div :class="$style.container" v-if="providersLoaded">
<p>
<strong>
It looks like your {{ localProvider.displayName }} account has become
disconnected
</strong>
</p>
<p :class="$style.small">Please re-connect to continue</p>
<p v-if="isInIframe">
We'll open the {{ localProvider.displayName }} authentication in a new
tab. Please return here and refresh the page once complete
</p>
<GoogleLikeButton
v-if="localProvider.viaIntegrationApp && crmTokenLoaded"
as="a"
:key="localProvider.name"
:brand-logo="localProvider.name"
:class="$style.connectButton"
@click="integrationAppOnClick"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
<GoogleLikeButton
v-if="!localProvider.viaIntegrationApp"
as="a"
:key="localProvider.name"
:href="`/auth/redirect/${localProvider.name}`"
:target="target"
:brand-logo="localProvider.name"
:class="$style.connectButton"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
</div>
<BuildInfo />
<KioskBanner />
</WelcomeLayout>
</template>
<script>
import window from "window";
import axios from "axios";
import { faUnlink } from "@fortawesome/pro-regular-svg-icons";
import isInIframe from "@/utils/isInIframe";
import BuildInfo from "@/components/layout/BuildInfo/BuildInfo.vue";
import KioskBanner from "@/components/shared/KioskBanner/KioskBanner.vue";
import WelcomeLayout from "@/components/layout/WelcomeLayout/WelcomeLayout.vue";
import GoogleLikeButton from "@/components/shared/Buttons/GoogleLikeButton.vue";
import { showSnackbarError, normalizeError } from "@/utils/index";
import { IntegrationAppClient } from "@integration-app/sdk";
export default {
name: "ConnectPage",
components: {
BuildInfo,
KioskBanner,
WelcomeLayout,
GoogleLikeButton,
},
data() {
return {
...window.connectData,
crmToken: null,
faUnlink,
isInIframe,
providers: [],
providersLoaded: false,
crmTokenLoaded: false,
};
},
computed: {
localProvider() {
return this.providers.find((e) => e.name === this.provider);
},
target() {
return this.isInIframe ? "_blank" : null;
},
},
created() {
this.getProviders();
},
mounted() {
this.showErrors();
},
watch: {
providersLoaded() {
if (this.providersLoaded) {
this.prepareIntegrationAppConnection();
}
},
},
methods: {
showErrors() {
if (!this.error) return;
showSnackbarError(this.error, undefined, undefined, false);
},
unwrapEntityResponse({ data }) {
return data.map(({ icon, name, displayName, viaIntegrationApp }) => {
return { icon, name, displayName, viaIntegrationApp };
});
},
async getProviders() {
try {
const response = await axios.get("/api/v1/connect-providers");
this.providers = this.unwrapEntityResponse(response);
this.providersLoaded = true;
} catch {
showSnackbarError(
"An error occurred, while loading form data (connect providers).",
);
}
},
async prepareIntegrationAppConnection() {
if (this.localProvider.viaIntegrationApp) {
try {
const response = await axios.get("/api/v1/integration-app-token");
this.crmToken = response.data.token;
this.crmTokenLoaded = true;
} catch (error) {
console.log(error);
showSnackbarError(
`An error occurred while preparing the page.
Try refreshing, if the error persists get in touch with the Jiminny team.`,
);
}
}
},
async integrationAppOnClick() {
console.log('[IntegrationApp] integrationAppOnClick called');
const integrationApp = new IntegrationAppClient({
token: this.crmToken,
});
const connection = await integrationApp
.integration(this.localProvider.name)
.openNewConnection({
showPoweredBy: false,
allowMultipleConnections: false,
}).catch((err) => {
console.log('[IntegrationApp] openNewConnection rejected:', err);
return null;
});
console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));
// [IntegrationApp] openNewConnection resolved: {
// "id":"69e0b41a67d0068c2ca0b48e",
// "name":"Zoho CRM",
// "userId":"1ece66c8-feb1-4df1-b321-21607daf4623",
// "tenantId":"69e0b3faef3e7b6248189289",
// "isTest":false,
// "connected":true,
// "state":"READY",
// "errors":[],
// "integrationId":"66fe6c913202f3a165e3c14d",
// "externalAppId":"6671653e7e2d642e4e41b0fa",
// "authOptionKey":"",
// "createdAt":"2026-04-16T10:04:10.420Z",
// "updatedAt":"2026-04-16T10:04:10.575Z",
// "retryAttempts":0,
// "isDeactivated":false
// }
if (connection && connection.disconnected !== true && connection.connected !== false) {
console.log('[IntegrationApp] connection condition matched');
try {
const saveRequest = await axios.post(
"/api/v1/integration-app-connect",
);
if (saveRequest.data && saveRequest.data.success === true) {
/** If all is good refresh the page here */
window.location = "/dashboard";
return;
}
throw new Error(saveRequest.data.message);
} catch (error) {
console.log(error);
showSnackbarError(normalizeError(error));
}
}
},
},
};
</script>
<style module lang="less" src="./connect.less"></style>
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
|
46970
|
NULL
|
0
|
2026-04-17T10:58:19.608434+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423499608_m2.jpg...
|
PhpStorm
|
faVsco.js – ~/jiminny/app/front-end/src/components faVsco.js – ~/jiminny/app/front-end/src/components/connect/connect.vue...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Code changed:
Hide
Sync Changes
Hide This Notification
33
2
19
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use HubSpot\Client\Crm\Deals\Model\CollectionResponseAssociatedId;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\Account;
use Exception;
use Jiminny\Component\DealInsights\Forecast\Forecast;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Contact;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Exceptions\CrmException;
use Jiminny\Models\Opportunity;
use Illuminate\Support\Collection;
use Jiminny\Models\Stage;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Services\Crm\Hubspot\DealFieldsService;
use Jiminny\Services\Crm\Hubspot\OpportunitySyncStrategy\HubspotSingleSyncStrategy;
use Jiminny\Services\Crm\Hubspot\WebhookSyncBatchProcessor;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Utils\CurrencyFormatter;
/**
* Optimized sync methods for better performance
* These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains
*/
trait OpportunitySyncTrait
{
private const int BATCH_SIZE = 100;
private const int BATCH_PROCESS_SIZE = 800;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected DealFieldsService $dealFieldsService;
private ?array $cachedClosedDealStages = null;
private array $cachedBusinessProcesses = [];
private array $cachedStages = [];
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$parameters['config'] = $this->config;
$syncCount = 0;
$reportedTotal = 0;
$lastSyncedId = [];
try {
foreach ($strategies as $strategyName => $syncStrategy) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .
$strategyName
);
$total = 0;
$lastId = null;
$buffer = [];
// HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies
foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {
$buffer[] = $hsOpportunity;
// process every 800 rows (fits < 1 000 association limit)
if (\count($buffer) >= self::BATCH_PROCESS_SIZE) {
$syncCount += $this->processOpportunityBatch($buffer);
$buffer = [];
}
}
// leftovers
if ($buffer) {
$syncCount += $this->processOpportunityBatch($buffer);
}
$reportedTotal += $total;
$lastSyncedId = $lastId;
}
} catch (\HubSpot\Client\Crm\Deals\ApiException | CrmException $e) {
$this->handleSyncException($e, $parameters);
}
$this->logger->info(
'[HubSpot] Synced opportunities',
[
'team' => $this->team->getId(),
'sync_count' => $syncCount,
'total' => $reportedTotal,
'last_synced_id' => $lastSyncedId,
]
);
return $reportedTotal;
}
private function handleSyncException(\Throwable $e, array $parameters): void
{
if (($parameters['since'] ?? null) instanceof Carbon) {
$parameters['since'] = $parameters['since']->toDateTimeString();
}
$parameters['config'] = $this->config->getId();
$this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [
'teamId' => $this->team->getUuid(),
'parameters' => $parameters,
'reason' => $e->getMessage(),
]);
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,
);
$parameters = [
'config' => $this->config,
'crm_id' => $crmId,
];
try {
if (! $strategy instanceof HubspotSingleSyncStrategy) {
throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');
}
$hsOpportunity = $strategy->fetchOpportunity($parameters);
} catch (\HubSpot\Client\Crm\Deals\ApiException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->getUuid(),
'crmId' => $crmId,
'reason' => $e->getMessage(),
]);
return null;
}
$hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);
return $this->importOrUpdateOpportunity($hsOpportunity);
}
/**
* Process webhook-collected opportunity batches.
*
* Drains Redis sets containing company CRM IDs collected from webhook events
* and dispatches ImportOpportunityBatch jobs for batch processing.
*
* @return int Number of opportunity IDs dispatched to jobs
*/
public function batchSyncOpportunities(): int
{
$configId = $this->team->getCrmConfiguration()->getId();
return $this->batchProcessor->processBatchesForObjectType(
WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,
$configId
);
}
/**
* Import a batch of opportunities by their CRM IDs.
* Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().
*
* @param array<string> $crmIds HubSpot deal CRM IDs
*
* @return array{success: array, failed_ids: array, errors?: array<string, string>}
*/
public function importOpportunityBatchByIds(array $crmIds): array
{
$fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);
$allDeals = [];
foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {
$deals = $this->client->getOpportunitiesByIds($chunk, $fields);
foreach ($deals as $deal) {
$allDeals[] = $deal;
}
}
// IDs not returned by HubSpot are likely deleted or inaccessible deals.
// These are not failures — retrying won't bring them back.
$fetchedIds = array_map('strval', array_column($allDeals, 'id'));
$notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));
if (! empty($notFoundIds)) {
$this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [
'teamId' => $this->team->getId(),
'notFoundCount' => \count($notFoundIds),
'notFoundIds' => $notFoundIds,
'requestedCount' => \count($crmIds),
'fetchedCount' => \count($allDeals),
]);
}
if (empty($allDeals)) {
return ['success' => [], 'failed_ids' => []];
}
return $this->importOpportunityBatch($allDeals);
}
private function getClosedDealStages(): array
{
if ($this->cachedClosedDealStages !== null) {
return $this->cachedClosedDealStages;
}
$stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);
$data = [
'lost' => [],
'won' => [],
];
foreach ($stages as $stage) {
if ($stage->probability == 0.00) {
$data['lost'][] = $stage->crm_provider_id;
}
if ($stage->probability == 100.00) {
$data['won'][] = $stage->crm_provider_id;
}
}
$this->cachedClosedDealStages = $data;
return $data;
}
/**
* Import deals into the database with pre-fetched associations.
*
* API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT
* caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()
* where Laravel retries the whole job with backoff. After all retries exhausted,
* failed() requeues all IDs to Redis.
*
* The per-deal loop catches exceptions individually. A deal can end up in three states:
* - success: imported/updated successfully
* - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)
* These are permanent issues — retrying won't fix them.
* - skipped (null): missing dependencies (no account, unknown pipeline/stage).
* This is acceptable — the deal cannot be imported until those exist.
*/
private function importOpportunityBatch(array $deals): array
{
$syncedOpportunities = [
'success' => [],
'failed_ids' => [],
];
$dealIds = array_column($deals, 'id');
// Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the
// queue job retries the whole batch and eventually requeues all deal IDs back to Redis.
try {
$companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');
$contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');
$associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);
$existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(
$this->config,
array_map('strval', $dealIds)
);
$existingCrmIdSet = array_flip($existingCrmIds);
} catch (\Throwable $e) {
$this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [
'teamId' => $this->team->getId(),
'dealCount' => count($dealIds),
'error' => $e->getMessage(),
]);
throw $e;
}
foreach ($deals as $deal) {
try {
$deal['associations'] = $this->prepareAssociationsForOpportunity(
$deal['id'],
$companyAssociations,
$contactAssociations,
$associationsData
);
$syncedOpportunity = $this->importOrUpdateOpportunity(
$deal,
isset($existingCrmIdSet[(string) $deal['id']])
);
if ($syncedOpportunity) {
$syncedOpportunities['success'][] = $syncedOpportunity;
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [
'teamId' => $this->team->getId(),
'crmId' => $deal['id'],
'error' => $e->getMessage(),
]);
$syncedOpportunities['failed_ids'][] = $deal['id'];
$syncedOpportunities['errors'][$deal['id']] = $e->getMessage();
}
}
return $syncedOpportunities;
}
/**
* Prepare associated entities for opportunities with optimized batch processing
* Returns structured data with CRM ID to DB ID mappings for each opportunity
*/
private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array
{
// Step 1: Collect all unique company and contact IDs from associations
$allCompanyIds = $this->flattenAssociationIds($companyAssociations);
$allContactIds = $this->flattenAssociationIds($contactAssociations);
// Step 2: Batch sync missing entities and get CRM ID to DB ID mappings
$companyIdMappings = [];
$contactIdMappings = [];
if (! empty($allCompanyIds)) {
$companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);
}
if (! empty($allContactIds)) {
$contactIdMappings = $this->prepareAssociatedContacts($allContactIds);
}
return [
'company_id_mappings' => $companyIdMappings,
'contact_id_mappings' => $contactIdMappings,
];
}
/**
* Flatten association data to get unique IDs
*/
private function flattenAssociationIds(array $associations): array
{
$ids = [];
foreach ($associations as $dealAssociations) {
if (is_array($dealAssociations)) {
foreach ($dealAssociations as $id) {
$ids[$id] = true;
}
}
}
return array_keys($ids);
}
/**
* Batch sync missing accounts
*/
private function prepareAssociatedAccounts(array $companyIds): array
{
// Find which accounts already exist
$existingAccounts = $this->crmEntityRepository
->findAccountsByExternalIds($this->config, $companyIds);
$existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();
$existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {
return [$account->getCrmProviderId() => $account->getId()];
})->toArray();
$missingCompanyIds = array_diff($companyIds, $existingCompanyIds);
if (empty($missingCompanyIds)) {
return $existingAccountsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [
'teamId' => $this->team->getUuid(),
'total_companies' => count($companyIds),
'existing_companies' => count($existingCompanyIds),
'missing_companies' => count($missingCompanyIds),
]);
// we already have limit on opportunity ids count
// Initialize variable before try block
$syncedAccountsData = [];
try {
$syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [
'size' => count($missingCompanyIds),
'error' => $e->getMessage(),
]);
$syncedAccountsData = [];
}
return $existingAccountsData + $syncedAccountsData;
}
/**
* Prepare associated contacts - find existing and sync missing ones
* Returns mapping of CRM ID to DB ID
*/
private function prepareAssociatedContacts(array $contactIds): array
{
// Find which contacts already exist
$existingContacts = $this->crmEntityRepository
->findContactsByExternalIds($this->config, $contactIds);
$existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();
// Create mapping for existing contacts
$existingContactsData = $existingContacts->mapWithKeys(function ($contact) {
return [$contact->getCrmProviderId() => $contact->getId()];
})->toArray();
$missingContactIds = array_diff($contactIds, $existingContactIds);
if (empty($missingContactIds)) {
return $existingContactsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [
'teamId' => $this->team->getUuid(),
'total_contacts' => count($contactIds),
'existing_contacts' => count($existingContactIds),
'missing_contacts' => count($missingContactIds),
]);
// Sync missing contacts using batch API
try {
$syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [
'size' => count($missingContactIds),
'error' => $e->getMessage(),
]);
$syncedContactsData = [];
}
return $existingContactsData + $syncedContactsData;
}
private function batchSyncCrmObjects(string $objectType, array $crmIds): array
{
$syncObjects = [];
$crmObjectIds = array_values($crmIds);
foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {
try {
$objects = $objectType === 'companies' ?
$this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :
$this->client->getContactsByIds($chunk, $this->getContactFields());
foreach ($objects as $objectId => $objectData) {
$this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [
'requested_count' => count($chunk),
'synced_count' => count($objects),
]);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [
'ids' => $chunk,
'error' => $e->getMessage(),
]);
}
}
return $syncObjects;
}
private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void
{
try {
$object = $objectType === 'companies' ?
$this->importAccount($objectData) :
$this->importContact($objectData);
if ($object) {
$syncObjects[$object->getCrmProviderId()] = $object->getId();
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [
'id' => $objectId,
'error' => $e->getMessage(),
]);
}
}
/**
* Prepare associations for a single opportunity
*
* The return value is an array with the following structure:
* [
* 'companies' => [
* $companyCrmId => $companyId,
* ...
* ],
* 'contacts' => [
* $contactCrmId => $contactId,
* ...
* ],
* 'account_id' => $accountId,
* ]
*/
private function prepareAssociationsForOpportunity(
string $oppCrmId,
array $companyAssociations,
array $contactAssociations,
array $associationsData
): array {
$associations = [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
$oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];
foreach ($oppCompanyIds as $companyCrmId) {
if (isset($associationsData['company_id_mappings'][$companyCrmId])) {
$associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];
// Set primary account (first company becomes primary account)
if ($associations['account_id'] === null) {
$associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];
}
}
}
$oppContactIds = $contactAssociations[$oppCrmId] ?? [];
foreach ($oppContactIds as $contactCrmId) {
if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {
$associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];
}
}
return $associations;
}
/**
* Update only associations for an opportunity
*/
private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void
{
// Update contact associations
$this->importOpportunityContacts($opportunity, $associations['contacts']);
// Update company (account) associations
$this->updateOpportunityAccount($opportunity, $associations['account_id']);
}
/**
* Remove all contact associations from an opportunity
*/
private function removeAllOpportunityContacts(Opportunity $opportunity): void
{
$currentCount = (int) $opportunity->contacts()->count();
if ($currentCount > 0) {
$opportunity->contacts()->detach();
$this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_count' => $currentCount,
]);
}
}
private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void
{
if ($accountId === null) {
// No account ID provided - keep current account
return;
}
$currentAccountId = $opportunity->getAccountId();
// Only update if account has changed
if ($currentAccountId !== $accountId) {
$opportunity->account_id = $accountId;
$opportunity->save();
$this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [
'opportunity_id' => $opportunity->getId(),
'old_account_id' => $currentAccountId,
'new_account_id' => $accountId,
]);
}
}
/**
* Find existing opportunities by external IDs (OPTIMIZED VERSION)
* Uses batch query for better performance
*/
private function findExistingOpportunities(array $crmIds): Collection
{
return $this->crmEntityRepository
->findOpportunitiesByExternalIds($this->config, $crmIds);
}
private function processOpportunityBatch(array $opportunities): int
{
$syncedOpportunities = $this->importOpportunityBatch($opportunities);
return count($syncedOpportunities['success'] ?? []);
}
/**
* Convert single deal associations from HubSpot format to internal format
* Handles both HubSpot SDK objects and array formats
*
* @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed
*
* @return array Processed associations with DB IDs
*/
private function convertDealAssociations(array $opportunityAssociations): array
{
$associations = $this->initializeAssociationsStructure();
if (empty($opportunityAssociations)) {
return $associations;
}
$associationIds = $this->extractAssociationIds($opportunityAssociations);
$this->processCompanyAssociations($associationIds, $associations);
$this->processContactAssociations($associationIds, $associations);
return $associations;
}
private function initializeAssociationsStructure(): array
{
return [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
}
private function extractAssociationIds(array $opportunityAssociations): array
{
$associationIds = [];
foreach ($opportunityAssociations as $type => $associationData) {
if (! empty($associationData)) {
$associationIds[$type] = $this->convertSingleDealAssociations($associationData);
}
}
return $associationIds;
}
private function processCompanyAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['companies'])) {
return;
}
$companyId = $associationIds['companies'][0];
$account = $this->findOrSyncAccount($companyId);
if ($account instanceof Account) {
$associations['companies'][$companyId] = $account->getId();
$associations['account_id'] = $account->getId();
}
}
private function processContactAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['contacts'])) {
return;
}
foreach ($associationIds['contacts'] as $contactId) {
$contact = $this->findOrSyncContact($contactId);
if ($contact instanceof Contact) {
$associations['contacts'][$contactId] = $contact->getId();
}
}
}
private function findOrSyncAccount(string $companyId): ?Account
{
$account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);
if (! $account instanceof Account) {
$account = $this->syncAccount($companyId);
}
return $account;
}
private function findOrSyncContact(string $contactId): ?Contact
{
$contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);
if (! $contact instanceof Contact) {
$contact = $this->syncContact($contactId);
}
return $contact;
}
private function convertSingleDealAssociations($opportunityAssociations = null): array
{
$associationData = [];
if ($opportunityAssociations === null) {
return $associationData;
}
// Handle array input (from extractAssociationIds)
if (is_array($opportunityAssociations)) {
return $opportunityAssociations;
}
// Handle CollectionResponseAssociatedId object
if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {
foreach ($opportunityAssociations->getResults() as $association) {
$associationData[] = $association->getId();
}
}
return $associationData;
}
private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity
{
if (empty($crmData['properties'])) {
return null;
}
$crmId = (string) $crmData['id'];
$properties = $crmData['properties'];
$associations = $crmData['associations'] ?? [];
$opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(
$this->config,
$crmId
);
if ($opportunityExists) {
return $this->updateOpportunity($crmId, $properties, $associations);
} else {
return $this->createOpportunity($crmId, $properties, $associations);
}
}
/**
* Create new opportunity
*/
private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity
{
$accountId = $this->resolveAccountId($associations);
if (! $accountId) {
return null;
}
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
if (! $businessProcess) {
return null;
}
$stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);
if (! $stage) {
return null;
}
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->importOpportunityContacts($opportunity, $associations['contacts']);
if ($opportunity->wasRecentlyCreated) {
MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());
}
return $opportunity;
}
/**
* Update existing opportunity
*/
private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity
{
$accountId = $this->resolveAccountId($associations);
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
$stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->updateOpportunityAssociations($opportunity, $associations);
return $opportunity;
}
private function resolveAccountId(array $associations): ?int
{
if (! empty($associations['accountId'])) {
return $associations['accountId'];
}
if (empty($associations)) {
return null;
}
// we can't resolve multiple account ids (currently SDK returns one company)
foreach ($associations['companies'] as $accountId) {
return $accountId;
}
return null;
}
private function buildOpportunityData(
array $properties,
?int $accountId,
?BusinessProcess $businessProcess,
?Stage $stage
): array {
$ownerId = null;
$profile = null;
if (! empty($properties['hubspot_owner_id'])) {
$ownerId = $properties['hubspot_owner_id'];
$profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);
}
$name = 'Unknown';
if (isset($properties['dealname'])) {
$name = mb_strimwidth($properties['dealname'], 0, 128);
}
$amount = $this->resolveAmount($properties);
$currency = $properties['deal_currency_code'] ?? null;
$closeDate = null;
if (! empty($properties['closedate'])) {
$closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');
}
$remotelyCreatedAt = null;
if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {
$date = $this->parseCleanDatetime($properties['createdate']);
$remotelyCreatedAt = $date?->format('Y-m-d H:i:s');
}
$closedStages = $this->getClosedDealStages();
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$data = [
'team_id' => $this->team->getId(),
'user_id' => $profile ? $profile->user_id : null,
'owner_id' => $ownerId,
'name' => $name,
'value' => ! empty($amount) ? $amount : null,
'currency_code' => CurrencyFormatter::formatCode($currency),
'close_date' => $closeDate,
'is_closed' => $isWon || $isLost,
'is_won' => $isWon,
'remotely_created_at' => $remotelyCreatedAt,
'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),
'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),
];
if ($accountId) {
$data['account_id'] = $accountId;
}
if ($stage) {
$data['stage_id'] = $stage->id;
}
if ($businessProcess) {
$recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);
if ($recordType) {
$data['record_type_id'] = $recordType->id;
}
}
return $data;
}
private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess
{
if ($pipelineId === null) {
return null;
}
if (isset($this->cachedBusinessProcesses[$pipelineId])) {
return $this->cachedBusinessProcesses[$pipelineId];
}
$businessProcess = $this->getBusinessProcess($pipelineId);
if (! $businessProcess instanceof BusinessProcess) {
$this->importStages();
$businessProcess = $this->getBusinessProcess($pipelineId);
}
if (! $businessProcess instanceof BusinessProcess) {
$this->logger->info(
'[HubSpot] Deal is not attached to a pipeline',
[
'pipeline' => $pipelineId]
);
}
$this->cachedBusinessProcesses[$pipelineId] = $businessProcess;
return $businessProcess;
}
private function getBusinessProcess(string $pipelineId): ?BusinessProcess
{
return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);
}
private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage
{
if (empty($stageId)) {
return null;
}
$cacheKey = $businessProcess->getId() . ':' . $stageId;
if (isset($this->cachedStages[$cacheKey])) {
return $this->cachedStages[$cacheKey];
}
$stage = $this->crmEntityRepository->getPipelineStageByConditions(
$businessProcess,
[
'crm_provider_id' => $stageId,
'type' => Stage::TYPE_OPPORTUNITY,
]
);
if ($stage === null) {
$this->importStages(null, $stageId);
}
if ($stage === null) {
$this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);
}
$this->cachedStages[$cacheKey] = $stage;
return $stage;
}
private function resolveAmount(array $properties): ?string
{
$amount = null;
if (! empty($properties['amount'])) {
$amount = str_replace(',', '', $properties['amount']);
}
if ($this->config->hasDefaultCurrencyFieldSet()) {
$valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();
$amount = $properties[$valueFieldName] ?? $amount;
}
return $amount;
}
private function parseCleanDatetime(string $datetime): ?Carbon
{
// Treat pre-1980 values as invalid
$minValidDate = Carbon::parse('1980-01-01 00:00:00');
try {
$date = Carbon::parse($datetime);
if ($minValidDate->gt($date)) {
return null;
}
return $date;
} catch (Exception) {
return null; // On parse error, treat as null
}
}
private function resolveDealProbability(?string $stageProbability): int
{
if ($stageProbability === null) {
return 0;
}
$probability = (float) $stageProbability;
return $probability > 1 ? 0 : (int) ($probability * 100);
}
private function resolveForecastCategory(?string $forecastCategory): string
{
if (! $forecastCategory) {
return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;
}
$forecastCategory = str_replace('_', ' ', $forecastCategory);
return ucwords(strtolower($forecastCategory));
}
private function importExternalFieldData(array $properties, int $opportunityId): void
{
$crmFields = $this->getOpportunitySyncableFields();
$this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);
}
private function importOpportunityContacts(Opportunity $opportunity, array $associations): void
{
// Handle empty or missing contact associations
if (empty($associations)) {
// Remove all existing contact associations if none provided
$this->removeAllOpportunityContacts($opportunity);
return;
}
// Use differential sync approach for better performance and accuracy
$this->syncOpportunityContactsDifferential($opportunity, $associations);
}
/**
* Sync opportunity contacts using differential approach
* This compares current vs new associations and only makes necessary changes
*/
private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void
{
$currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);
$contactAssociationIds = array_keys($contactAssociations);
$contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);
$contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);
if (empty($contactsToAdd) && empty($contactsToRemove)) {
return;
}
$this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);
$this->removeContactAssociations($opportunity, $contactsToRemove);
$this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);
}
private function getCurrentContactCrmIds(Opportunity $opportunity): array
{
return $opportunity->contacts()
->pluck('contacts.crm_provider_id')
->toArray();
}
private function logContactAssociationChanges(
Opportunity $opportunity,
array $currentContactCrmIds,
array $contactAssociations,
array $contactsToAdd,
array $contactsToRemove
): void {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [
'opportunity_id' => $opportunity->getId(),
'current_contacts' => $currentContactCrmIds,
'new_contacts' => $contactAssociations,
'contacts_to_add' => $contactsToAdd,
'contacts_to_remove' => $contactsToRemove,
]);
}
private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void
{
if (empty($contactsToRemove)) {
return;
}
$contactsToDetach = $opportunity->contacts()
->whereIn('contacts.crm_provider_id', $contactsToRemove)
->pluck('contacts.id')
->toArray();
if (! empty($contactsToDetach)) {
$opportunity->contacts()->detach($contactsToDetach);
$this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_contact_crm_ids' => $contactsToRemove,
'removed_contact_count' => count($contactsToDetach),
]);
}
}
private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void
{
if (empty($contactsToAdd)) {
return;
}
$contactsAdded = [];
foreach ($contactsToAdd as $crmId) {
$id = $contactAssociations[$crmId];
if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {
$contactsAdded[] = $crmId;
}
}
$this->logAddedContacts($opportunity, $contactsAdded);
}
private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool
{
try {
$contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);
if (! $contact) {
return false;
}
return $this->performContactAttachment($opportunity, $contact, $crmId);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [
'opportunity_id' => $opportunity->getId(),
'contact_crm_id' => $crmId,
'error' => $e->getMessage(),
]);
return false;
}
}
private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool
{
try {
$opportunity->contacts()->attach($contact->getId(), [
'crm_provider_id' => $crmId,
]);
return true;
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [
'contact_id' => $contact->getId(),
'contact_crm_id' => $crmId,
'opportunity_id' => $opportunity->getId(),
]);
return false;
}
throw $e;
}
}
private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void
{
if (! empty($contactsAdded)) {
$this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [
'opportunity_id' => $opportunity->getId(),
'contacts_to_add_count' => count($contactsAdded),
'added_contact_crm_ids' => $contactsAdded,
'added_contacts_count' => count($contactsAdded),
]);
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<template>
<WelcomeLayout
title="Account disconnected"
textPosition="center"
:icon="faUnlink"
:class="$style.layout"
>
<div :class="$style.container" v-if="providersLoaded">
<p>
<strong>
It looks like your {{ localProvider.displayName }} account has become
disconnected
</strong>
</p>
<p :class="$style.small">Please re-connect to continue</p>
<p v-if="isInIframe">
We'll open the {{ localProvider.displayName }} authentication in a new
tab. Please return here and refresh the page once complete
</p>
<GoogleLikeButton
v-if="localProvider.viaIntegrationApp && crmTokenLoaded"
as="a"
:key="localProvider.name"
:brand-logo="localProvider.name"
:class="$style.connectButton"
@click="integrationAppOnClick"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
<GoogleLikeButton
v-if="!localProvider.viaIntegrationApp"
as="a"
:key="localProvider.name"
:href="`/auth/redirect/${localProvider.name}`"
:target="target"
:brand-logo="localProvider.name"
:class="$style.connectButton"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
</div>
<BuildInfo />
<KioskBanner />
</WelcomeLayout>
</template>
<script>
import window from "window";
import axios from "axios";
import { faUnlink } from "@fortawesome/pro-regular-svg-icons";
import isInIframe from "@/utils/isInIframe";
import BuildInfo from "@/components/layout/BuildInfo/BuildInfo.vue";
import KioskBanner from "@/components/shared/KioskBanner/KioskBanner.vue";
import WelcomeLayout from "@/components/layout/WelcomeLayout/WelcomeLayout.vue";
import GoogleLikeButton from "@/components/shared/Buttons/GoogleLikeButton.vue";
import { showSnackbarError, normalizeError } from "@/utils/index";
import { IntegrationAppClient } from "@integration-app/sdk";
export default {
name: "ConnectPage",
components: {
BuildInfo,
KioskBanner,
WelcomeLayout,
GoogleLikeButton,
},
data() {
return {
...window.connectData,
crmToken: null,
faUnlink,
isInIframe,
providers: [],
providersLoaded: false,
crmTokenLoaded: false,
};
},
computed: {
localProvider() {
return this.providers.find((e) => e.name === this.provider);
},
target() {
return this.isInIframe ? "_blank" : null;
},
},
created() {
this.getProviders();
},
mounted() {
this.showErrors();
},
watch: {
providersLoaded() {
if (this.providersLoaded) {
this.prepareIntegrationAppConnection();
}
},
},
methods: {
showErrors() {
if (!this.error) return;
showSnackbarError(this.error, undefined, undefined, false);
},
unwrapEntityResponse({ data }) {
return data.map(({ icon, name, displayName, viaIntegrationApp }) => {
return { icon, name, displayName, viaIntegrationApp };
});
},
async getProviders() {
try {
const response = await axios.get("/api/v1/connect-providers");
this.providers = this.unwrapEntityResponse(response);
this.providersLoaded = true;
} catch {
showSnackbarError(
"An error occurred, while loading form data (connect providers).",
);
}
},
async prepareIntegrationAppConnection() {
if (this.localProvider.viaIntegrationApp) {
try {
const response = await axios.get("/api/v1/integration-app-token");
this.crmToken = response.data.token;
this.crmTokenLoaded = true;
} catch (error) {
console.log(error);
showSnackbarError(
`An error occurred while preparing the page.
Try refreshing, if the error persists get in touch with the Jiminny team.`,
);
}
}
},
async integrationAppOnClick() {
console.log('[IntegrationApp] integrationAppOnClick called');
const integrationApp = new IntegrationAppClient({
token: this.crmToken,
});
const connection = await integrationApp
.integration(this.localProvider.name)
.openNewConnection({
showPoweredBy: false,
allowMultipleConnections: false,
}).catch((err) => {
console.log('[IntegrationApp] openNewConnection rejected:', err);
return null;
});
console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));
// [IntegrationApp] openNewConnection resolved: {
// "id":"69e0b41a67d0068c2ca0b48e",
// "name":"Zoho CRM",
// "userId":"1ece66c8-feb1-4df1-b321-21607daf4623",
// "tenantId":"69e0b3faef3e7b6248189289",
// "isTest":false,
// "connected":true,
// "state":"READY",
// "errors":[],
// "integrationId":"66fe6c913202f3a165e3c14d",
// "externalAppId":"6671653e7e2d642e4e41b0fa",
// "authOptionKey":"",
// "createdAt":"2026-04-16T10:04:10.420Z",
// "updatedAt":"2026-04-16T10:04:10.575Z",
// "retryAttempts":0,
// "isDeactivated":false
// }
if (connection && connection.disconnected !== true && connection.connected !== false) {
console.log('[IntegrationApp] connection condition matched');
try {
const saveRequest = await axios.post(
"/api/v1/integration-app-connect",
);
if (saveRequest.data && saveRequest.data.success === true) {
/** If all is good refresh the page here */
window.location = "/dashboard";
return;
}
throw new Error(saveRequest.data.message);
} catch (error) {
console.log(error);
showSnackbarError(normalizeError(error));
}
}
},
},
};
</script>
<style module lang="less" src="./connect.less"></style>...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.03046875,"top":0.017361112,"width":0.0453125,"height":0.022222223},"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"bounds":{"left":0.07578125,"top":0.017361112,"width":0.15898438,"height":0.022222223},"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.78515625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"bounds":{"left":0.803125,"top":0.017361112,"width":0.09765625,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9007813,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9140625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9273437,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96015626,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9734375,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9867188,"top":0.017361112,"width":0.013281226,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.12382813,"top":0.22083333,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.13867188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"bounds":{"left":0.1515625,"top":0.22013889,"width":0.0515625,"height":0.013888889},"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.21367188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.22539063,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.23554687,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.24570313,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":4,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2/4","depth":4,"bounds":{"left":0.26171875,"top":0.21944444,"width":0.030078124,"height":0.015277778},"role_description":"text"},{"role":"AXButton","text":"Previous Occurrence","depth":4,"bounds":{"left":0.29179686,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Occurrence","depth":4,"bounds":{"left":0.30195314,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":4,"bounds":{"left":0.31210938,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Window, Multiple Cursors","depth":4,"bounds":{"left":0.32226562,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Click to highlight","depth":4,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":4,"bounds":{"left":0.38320312,"top":0.21875,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.049609374,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"33","depth":4,"bounds":{"left":0.3421875,"top":0.24583334,"width":0.012109375,"height":0.013194445},"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"bounds":{"left":0.35664064,"top":0.24583334,"width":0.009375,"height":0.013194445},"role_description":"text"},{"role":"AXStaticText","text":"19","depth":4,"bounds":{"left":0.3683594,"top":0.24583334,"width":0.011328125,"height":0.013194445},"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.3816406,"top":0.24444444,"width":0.00859375,"height":0.015972223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.39023438,"top":0.24444444,"width":0.008203125,"height":0.015972223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\CollectionResponseAssociatedId;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\Account;\nuse Exception;\nuse Jiminny\\Component\\DealInsights\\Forecast\\Forecast;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Models\\Opportunity;\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Repositories\\Crm\\CrmEntityRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DealFieldsService;\nuse Jiminny\\Services\\Crm\\Hubspot\\OpportunitySyncStrategy\\HubspotSingleSyncStrategy;\nuse Jiminny\\Services\\Crm\\Hubspot\\WebhookSyncBatchProcessor;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Utils\\CurrencyFormatter;\n\n/**\n * Optimized sync methods for better performance\n * These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains\n */\ntrait OpportunitySyncTrait\n{\n private const int BATCH_SIZE = 100;\n private const int BATCH_PROCESS_SIZE = 800;\n\n protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n protected CrmEntityRepository $crmEntityRepository;\n protected DealFieldsService $dealFieldsService;\n\n private ?array $cachedClosedDealStages = null;\n private array $cachedBusinessProcesses = [];\n private array $cachedStages = [];\n\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n $parameters['config'] = $this->config;\n $syncCount = 0;\n $reportedTotal = 0;\n $lastSyncedId = [];\n\n try {\n foreach ($strategies as $strategyName => $syncStrategy) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .\n $strategyName\n );\n\n $total = 0;\n $lastId = null;\n $buffer = [];\n\n // HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies\n foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {\n $buffer[] = $hsOpportunity;\n\n // process every 800 rows (fits < 1 000 association limit)\n if (\\count($buffer) >= self::BATCH_PROCESS_SIZE) {\n $syncCount += $this->processOpportunityBatch($buffer);\n $buffer = [];\n }\n }\n\n // leftovers\n if ($buffer) {\n $syncCount += $this->processOpportunityBatch($buffer);\n }\n\n $reportedTotal += $total;\n $lastSyncedId = $lastId;\n }\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException | CrmException $e) {\n $this->handleSyncException($e, $parameters);\n }\n\n $this->logger->info(\n '[HubSpot] Synced opportunities',\n [\n 'team' => $this->team->getId(),\n 'sync_count' => $syncCount,\n 'total' => $reportedTotal,\n 'last_synced_id' => $lastSyncedId,\n ]\n );\n\n return $reportedTotal;\n }\n\n private function handleSyncException(\\Throwable $e, array $parameters): void\n {\n if (($parameters['since'] ?? null) instanceof Carbon) {\n $parameters['since'] = $parameters['since']->toDateTimeString();\n }\n $parameters['config'] = $this->config->getId();\n\n $this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [\n 'teamId' => $this->team->getUuid(),\n 'parameters' => $parameters,\n 'reason' => $e->getMessage(),\n ]);\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,\n );\n\n $parameters = [\n 'config' => $this->config,\n 'crm_id' => $crmId,\n ];\n\n try {\n if (! $strategy instanceof HubspotSingleSyncStrategy) {\n throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');\n }\n\n $hsOpportunity = $strategy->fetchOpportunity($parameters);\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->getUuid(),\n 'crmId' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);\n\n return $this->importOrUpdateOpportunity($hsOpportunity);\n }\n\n /**\n * Process webhook-collected opportunity batches.\n *\n * Drains Redis sets containing company CRM IDs collected from webhook events\n * and dispatches ImportOpportunityBatch jobs for batch processing.\n *\n * @return int Number of opportunity IDs dispatched to jobs\n */\n public function batchSyncOpportunities(): int\n {\n $configId = $this->team->getCrmConfiguration()->getId();\n\n return $this->batchProcessor->processBatchesForObjectType(\n WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,\n $configId\n );\n }\n\n /**\n * Import a batch of opportunities by their CRM IDs.\n * Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().\n *\n * @param array<string> $crmIds HubSpot deal CRM IDs\n *\n * @return array{success: array, failed_ids: array, errors?: array<string, string>}\n */\n public function importOpportunityBatchByIds(array $crmIds): array\n {\n $fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);\n\n $allDeals = [];\n foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {\n $deals = $this->client->getOpportunitiesByIds($chunk, $fields);\n foreach ($deals as $deal) {\n $allDeals[] = $deal;\n }\n }\n\n // IDs not returned by HubSpot are likely deleted or inaccessible deals.\n // These are not failures — retrying won't bring them back.\n $fetchedIds = array_map('strval', array_column($allDeals, 'id'));\n $notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));\n\n if (! empty($notFoundIds)) {\n $this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [\n 'teamId' => $this->team->getId(),\n 'notFoundCount' => \\count($notFoundIds),\n 'notFoundIds' => $notFoundIds,\n 'requestedCount' => \\count($crmIds),\n 'fetchedCount' => \\count($allDeals),\n ]);\n }\n\n if (empty($allDeals)) {\n return ['success' => [], 'failed_ids' => []];\n }\n\n return $this->importOpportunityBatch($allDeals);\n }\n\n private function getClosedDealStages(): array\n {\n if ($this->cachedClosedDealStages !== null) {\n return $this->cachedClosedDealStages;\n }\n\n $stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);\n $data = [\n 'lost' => [],\n 'won' => [],\n ];\n\n foreach ($stages as $stage) {\n if ($stage->probability == 0.00) {\n $data['lost'][] = $stage->crm_provider_id;\n }\n if ($stage->probability == 100.00) {\n $data['won'][] = $stage->crm_provider_id;\n }\n }\n\n $this->cachedClosedDealStages = $data;\n\n return $data;\n }\n\n /**\n * Import deals into the database with pre-fetched associations.\n *\n * API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT\n * caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()\n * where Laravel retries the whole job with backoff. After all retries exhausted,\n * failed() requeues all IDs to Redis.\n *\n * The per-deal loop catches exceptions individually. A deal can end up in three states:\n * - success: imported/updated successfully\n * - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)\n * These are permanent issues — retrying won't fix them.\n * - skipped (null): missing dependencies (no account, unknown pipeline/stage).\n * This is acceptable — the deal cannot be imported until those exist.\n */\n private function importOpportunityBatch(array $deals): array\n {\n $syncedOpportunities = [\n 'success' => [],\n 'failed_ids' => [],\n ];\n $dealIds = array_column($deals, 'id');\n\n // Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the\n // queue job retries the whole batch and eventually requeues all deal IDs back to Redis.\n try {\n $companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');\n $contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');\n\n $associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);\n\n $existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(\n $this->config,\n array_map('strval', $dealIds)\n );\n $existingCrmIdSet = array_flip($existingCrmIds);\n } catch (\\Throwable $e) {\n $this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [\n 'teamId' => $this->team->getId(),\n 'dealCount' => count($dealIds),\n 'error' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n foreach ($deals as $deal) {\n try {\n $deal['associations'] = $this->prepareAssociationsForOpportunity(\n $deal['id'],\n $companyAssociations,\n $contactAssociations,\n $associationsData\n );\n\n $syncedOpportunity = $this->importOrUpdateOpportunity(\n $deal,\n isset($existingCrmIdSet[(string) $deal['id']])\n );\n if ($syncedOpportunity) {\n $syncedOpportunities['success'][] = $syncedOpportunity;\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [\n 'teamId' => $this->team->getId(),\n 'crmId' => $deal['id'],\n 'error' => $e->getMessage(),\n ]);\n $syncedOpportunities['failed_ids'][] = $deal['id'];\n $syncedOpportunities['errors'][$deal['id']] = $e->getMessage();\n }\n }\n\n return $syncedOpportunities;\n }\n\n /**\n * Prepare associated entities for opportunities with optimized batch processing\n * Returns structured data with CRM ID to DB ID mappings for each opportunity\n */\n private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array\n {\n // Step 1: Collect all unique company and contact IDs from associations\n $allCompanyIds = $this->flattenAssociationIds($companyAssociations);\n $allContactIds = $this->flattenAssociationIds($contactAssociations);\n\n // Step 2: Batch sync missing entities and get CRM ID to DB ID mappings\n $companyIdMappings = [];\n $contactIdMappings = [];\n\n if (! empty($allCompanyIds)) {\n $companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);\n }\n\n if (! empty($allContactIds)) {\n $contactIdMappings = $this->prepareAssociatedContacts($allContactIds);\n }\n\n return [\n 'company_id_mappings' => $companyIdMappings,\n 'contact_id_mappings' => $contactIdMappings,\n ];\n }\n\n /**\n * Flatten association data to get unique IDs\n */\n private function flattenAssociationIds(array $associations): array\n {\n $ids = [];\n foreach ($associations as $dealAssociations) {\n if (is_array($dealAssociations)) {\n foreach ($dealAssociations as $id) {\n $ids[$id] = true;\n }\n }\n }\n\n return array_keys($ids);\n }\n\n /**\n * Batch sync missing accounts\n */\n private function prepareAssociatedAccounts(array $companyIds): array\n {\n // Find which accounts already exist\n $existingAccounts = $this->crmEntityRepository\n ->findAccountsByExternalIds($this->config, $companyIds);\n\n $existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();\n\n $existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {\n return [$account->getCrmProviderId() => $account->getId()];\n })->toArray();\n\n $missingCompanyIds = array_diff($companyIds, $existingCompanyIds);\n\n if (empty($missingCompanyIds)) {\n return $existingAccountsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [\n 'teamId' => $this->team->getUuid(),\n 'total_companies' => count($companyIds),\n 'existing_companies' => count($existingCompanyIds),\n 'missing_companies' => count($missingCompanyIds),\n ]);\n\n // we already have limit on opportunity ids count\n // Initialize variable before try block\n $syncedAccountsData = [];\n\n try {\n $syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [\n 'size' => count($missingCompanyIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedAccountsData = [];\n }\n\n return $existingAccountsData + $syncedAccountsData;\n }\n\n /**\n * Prepare associated contacts - find existing and sync missing ones\n * Returns mapping of CRM ID to DB ID\n */\n private function prepareAssociatedContacts(array $contactIds): array\n {\n // Find which contacts already exist\n $existingContacts = $this->crmEntityRepository\n ->findContactsByExternalIds($this->config, $contactIds);\n\n $existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();\n\n // Create mapping for existing contacts\n $existingContactsData = $existingContacts->mapWithKeys(function ($contact) {\n return [$contact->getCrmProviderId() => $contact->getId()];\n })->toArray();\n\n $missingContactIds = array_diff($contactIds, $existingContactIds);\n\n if (empty($missingContactIds)) {\n return $existingContactsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [\n 'teamId' => $this->team->getUuid(),\n 'total_contacts' => count($contactIds),\n 'existing_contacts' => count($existingContactIds),\n 'missing_contacts' => count($missingContactIds),\n ]);\n\n // Sync missing contacts using batch API\n try {\n $syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [\n 'size' => count($missingContactIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedContactsData = [];\n }\n\n return $existingContactsData + $syncedContactsData;\n }\n\n private function batchSyncCrmObjects(string $objectType, array $crmIds): array\n {\n $syncObjects = [];\n $crmObjectIds = array_values($crmIds);\n\n foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {\n try {\n $objects = $objectType === 'companies' ?\n $this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :\n $this->client->getContactsByIds($chunk, $this->getContactFields());\n\n foreach ($objects as $objectId => $objectData) {\n $this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [\n 'requested_count' => count($chunk),\n 'synced_count' => count($objects),\n ]);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [\n 'ids' => $chunk,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n return $syncObjects;\n }\n\n private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void\n {\n try {\n $object = $objectType === 'companies' ?\n $this->importAccount($objectData) :\n $this->importContact($objectData);\n\n if ($object) {\n $syncObjects[$object->getCrmProviderId()] = $object->getId();\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [\n 'id' => $objectId,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * Prepare associations for a single opportunity\n *\n * The return value is an array with the following structure:\n * [\n * 'companies' => [\n * $companyCrmId => $companyId,\n * ...\n * ],\n * 'contacts' => [\n * $contactCrmId => $contactId,\n * ...\n * ],\n * 'account_id' => $accountId,\n * ]\n */\n private function prepareAssociationsForOpportunity(\n string $oppCrmId,\n array $companyAssociations,\n array $contactAssociations,\n array $associationsData\n ): array {\n $associations = [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n\n $oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];\n foreach ($oppCompanyIds as $companyCrmId) {\n if (isset($associationsData['company_id_mappings'][$companyCrmId])) {\n $associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];\n\n // Set primary account (first company becomes primary account)\n if ($associations['account_id'] === null) {\n $associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];\n }\n }\n }\n\n $oppContactIds = $contactAssociations[$oppCrmId] ?? [];\n foreach ($oppContactIds as $contactCrmId) {\n if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {\n $associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];\n }\n }\n\n return $associations;\n }\n\n /**\n * Update only associations for an opportunity\n */\n private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void\n {\n // Update contact associations\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n // Update company (account) associations\n $this->updateOpportunityAccount($opportunity, $associations['account_id']);\n }\n\n /**\n * Remove all contact associations from an opportunity\n */\n private function removeAllOpportunityContacts(Opportunity $opportunity): void\n {\n $currentCount = (int) $opportunity->contacts()->count();\n\n if ($currentCount > 0) {\n $opportunity->contacts()->detach();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_count' => $currentCount,\n ]);\n }\n }\n\n private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void\n {\n if ($accountId === null) {\n // No account ID provided - keep current account\n return;\n }\n\n $currentAccountId = $opportunity->getAccountId();\n\n // Only update if account has changed\n if ($currentAccountId !== $accountId) {\n $opportunity->account_id = $accountId;\n $opportunity->save();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [\n 'opportunity_id' => $opportunity->getId(),\n 'old_account_id' => $currentAccountId,\n 'new_account_id' => $accountId,\n ]);\n }\n }\n\n /**\n * Find existing opportunities by external IDs (OPTIMIZED VERSION)\n * Uses batch query for better performance\n */\n private function findExistingOpportunities(array $crmIds): Collection\n {\n return $this->crmEntityRepository\n ->findOpportunitiesByExternalIds($this->config, $crmIds);\n }\n\n private function processOpportunityBatch(array $opportunities): int\n {\n $syncedOpportunities = $this->importOpportunityBatch($opportunities);\n\n return count($syncedOpportunities['success'] ?? []);\n }\n\n /**\n * Convert single deal associations from HubSpot format to internal format\n * Handles both HubSpot SDK objects and array formats\n *\n * @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed\n *\n * @return array Processed associations with DB IDs\n */\n private function convertDealAssociations(array $opportunityAssociations): array\n {\n $associations = $this->initializeAssociationsStructure();\n\n if (empty($opportunityAssociations)) {\n return $associations;\n }\n\n $associationIds = $this->extractAssociationIds($opportunityAssociations);\n\n $this->processCompanyAssociations($associationIds, $associations);\n $this->processContactAssociations($associationIds, $associations);\n\n return $associations;\n }\n\n private function initializeAssociationsStructure(): array\n {\n return [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n }\n\n private function extractAssociationIds(array $opportunityAssociations): array\n {\n $associationIds = [];\n\n foreach ($opportunityAssociations as $type => $associationData) {\n if (! empty($associationData)) {\n $associationIds[$type] = $this->convertSingleDealAssociations($associationData);\n }\n }\n\n return $associationIds;\n }\n\n private function processCompanyAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['companies'])) {\n return;\n }\n\n $companyId = $associationIds['companies'][0];\n $account = $this->findOrSyncAccount($companyId);\n\n if ($account instanceof Account) {\n $associations['companies'][$companyId] = $account->getId();\n $associations['account_id'] = $account->getId();\n }\n }\n\n private function processContactAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['contacts'])) {\n return;\n }\n\n foreach ($associationIds['contacts'] as $contactId) {\n $contact = $this->findOrSyncContact($contactId);\n\n if ($contact instanceof Contact) {\n $associations['contacts'][$contactId] = $contact->getId();\n }\n }\n }\n\n private function findOrSyncAccount(string $companyId): ?Account\n {\n $account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);\n\n if (! $account instanceof Account) {\n $account = $this->syncAccount($companyId);\n }\n\n return $account;\n }\n\n private function findOrSyncContact(string $contactId): ?Contact\n {\n $contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);\n\n if (! $contact instanceof Contact) {\n $contact = $this->syncContact($contactId);\n }\n\n return $contact;\n }\n\n private function convertSingleDealAssociations($opportunityAssociations = null): array\n {\n $associationData = [];\n\n if ($opportunityAssociations === null) {\n return $associationData;\n }\n\n // Handle array input (from extractAssociationIds)\n if (is_array($opportunityAssociations)) {\n return $opportunityAssociations;\n }\n\n // Handle CollectionResponseAssociatedId object\n if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {\n foreach ($opportunityAssociations->getResults() as $association) {\n $associationData[] = $association->getId();\n }\n }\n\n return $associationData;\n }\n\n private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity\n {\n if (empty($crmData['properties'])) {\n return null;\n }\n\n $crmId = (string) $crmData['id'];\n $properties = $crmData['properties'];\n $associations = $crmData['associations'] ?? [];\n\n $opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(\n $this->config,\n $crmId\n );\n\n if ($opportunityExists) {\n return $this->updateOpportunity($crmId, $properties, $associations);\n } else {\n return $this->createOpportunity($crmId, $properties, $associations);\n }\n }\n\n /**\n * Create new opportunity\n */\n private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n if (! $accountId) {\n return null;\n }\n\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n if (! $businessProcess) {\n return null;\n }\n\n $stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);\n if (! $stage) {\n return null;\n }\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n }\n\n /**\n * Update existing opportunity\n */\n private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n $stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->updateOpportunityAssociations($opportunity, $associations);\n\n return $opportunity;\n }\n\n private function resolveAccountId(array $associations): ?int\n {\n if (! empty($associations['accountId'])) {\n return $associations['accountId'];\n }\n\n if (empty($associations)) {\n return null;\n }\n\n // we can't resolve multiple account ids (currently SDK returns one company)\n foreach ($associations['companies'] as $accountId) {\n return $accountId;\n }\n\n return null;\n }\n\n private function buildOpportunityData(\n array $properties,\n ?int $accountId,\n ?BusinessProcess $businessProcess,\n ?Stage $stage\n ): array {\n $ownerId = null;\n $profile = null;\n if (! empty($properties['hubspot_owner_id'])) {\n $ownerId = $properties['hubspot_owner_id'];\n $profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);\n }\n\n $name = 'Unknown';\n if (isset($properties['dealname'])) {\n $name = mb_strimwidth($properties['dealname'], 0, 128);\n }\n\n $amount = $this->resolveAmount($properties);\n $currency = $properties['deal_currency_code'] ?? null;\n\n $closeDate = null;\n if (! empty($properties['closedate'])) {\n $closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');\n }\n\n $remotelyCreatedAt = null;\n if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {\n $date = $this->parseCleanDatetime($properties['createdate']);\n $remotelyCreatedAt = $date?->format('Y-m-d H:i:s');\n }\n\n $closedStages = $this->getClosedDealStages();\n $isWon = in_array($properties['dealstage'], $closedStages['won']);\n $isLost = in_array($properties['dealstage'], $closedStages['lost']);\n\n $data = [\n 'team_id' => $this->team->getId(),\n 'user_id' => $profile ? $profile->user_id : null,\n 'owner_id' => $ownerId,\n 'name' => $name,\n 'value' => ! empty($amount) ? $amount : null,\n 'currency_code' => CurrencyFormatter::formatCode($currency),\n 'close_date' => $closeDate,\n 'is_closed' => $isWon || $isLost,\n 'is_won' => $isWon,\n 'remotely_created_at' => $remotelyCreatedAt,\n 'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),\n 'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),\n ];\n\n if ($accountId) {\n $data['account_id'] = $accountId;\n }\n\n if ($stage) {\n $data['stage_id'] = $stage->id;\n }\n\n if ($businessProcess) {\n $recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);\n if ($recordType) {\n $data['record_type_id'] = $recordType->id;\n }\n }\n\n return $data;\n }\n\n private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess\n {\n if ($pipelineId === null) {\n return null;\n }\n\n if (isset($this->cachedBusinessProcesses[$pipelineId])) {\n return $this->cachedBusinessProcesses[$pipelineId];\n }\n\n $businessProcess = $this->getBusinessProcess($pipelineId);\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->importStages();\n $businessProcess = $this->getBusinessProcess($pipelineId);\n }\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->logger->info(\n '[HubSpot] Deal is not attached to a pipeline',\n [\n 'pipeline' => $pipelineId]\n );\n }\n\n $this->cachedBusinessProcesses[$pipelineId] = $businessProcess;\n\n return $businessProcess;\n }\n\n private function getBusinessProcess(string $pipelineId): ?BusinessProcess\n {\n return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);\n }\n\n private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage\n {\n if (empty($stageId)) {\n return null;\n }\n\n $cacheKey = $businessProcess->getId() . ':' . $stageId;\n if (isset($this->cachedStages[$cacheKey])) {\n return $this->cachedStages[$cacheKey];\n }\n\n $stage = $this->crmEntityRepository->getPipelineStageByConditions(\n $businessProcess,\n [\n 'crm_provider_id' => $stageId,\n 'type' => Stage::TYPE_OPPORTUNITY,\n ]\n );\n\n if ($stage === null) {\n $this->importStages(null, $stageId);\n }\n\n if ($stage === null) {\n $this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);\n }\n\n $this->cachedStages[$cacheKey] = $stage;\n\n return $stage;\n }\n\n private function resolveAmount(array $properties): ?string\n {\n $amount = null;\n if (! empty($properties['amount'])) {\n $amount = str_replace(',', '', $properties['amount']);\n }\n\n if ($this->config->hasDefaultCurrencyFieldSet()) {\n $valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();\n $amount = $properties[$valueFieldName] ?? $amount;\n }\n\n return $amount;\n }\n\n private function parseCleanDatetime(string $datetime): ?Carbon\n {\n // Treat pre-1980 values as invalid\n $minValidDate = Carbon::parse('1980-01-01 00:00:00');\n\n try {\n $date = Carbon::parse($datetime);\n\n if ($minValidDate->gt($date)) {\n return null;\n }\n\n return $date;\n } catch (Exception) {\n return null; // On parse error, treat as null\n }\n }\n\n private function resolveDealProbability(?string $stageProbability): int\n {\n if ($stageProbability === null) {\n return 0;\n }\n\n $probability = (float) $stageProbability;\n\n return $probability > 1 ? 0 : (int) ($probability * 100);\n }\n\n private function resolveForecastCategory(?string $forecastCategory): string\n {\n if (! $forecastCategory) {\n return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;\n }\n\n $forecastCategory = str_replace('_', ' ', $forecastCategory);\n\n return ucwords(strtolower($forecastCategory));\n }\n\n private function importExternalFieldData(array $properties, int $opportunityId): void\n {\n $crmFields = $this->getOpportunitySyncableFields();\n $this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);\n }\n\n private function importOpportunityContacts(Opportunity $opportunity, array $associations): void\n {\n // Handle empty or missing contact associations\n if (empty($associations)) {\n // Remove all existing contact associations if none provided\n $this->removeAllOpportunityContacts($opportunity);\n\n return;\n }\n\n // Use differential sync approach for better performance and accuracy\n $this->syncOpportunityContactsDifferential($opportunity, $associations);\n }\n\n /**\n * Sync opportunity contacts using differential approach\n * This compares current vs new associations and only makes necessary changes\n */\n private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void\n {\n $currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);\n $contactAssociationIds = array_keys($contactAssociations);\n\n $contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);\n $contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);\n\n if (empty($contactsToAdd) && empty($contactsToRemove)) {\n return;\n }\n\n $this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);\n\n $this->removeContactAssociations($opportunity, $contactsToRemove);\n $this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);\n }\n\n private function getCurrentContactCrmIds(Opportunity $opportunity): array\n {\n return $opportunity->contacts()\n ->pluck('contacts.crm_provider_id')\n ->toArray();\n }\n\n private function logContactAssociationChanges(\n Opportunity $opportunity,\n array $currentContactCrmIds,\n array $contactAssociations,\n array $contactsToAdd,\n array $contactsToRemove\n ): void {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [\n 'opportunity_id' => $opportunity->getId(),\n 'current_contacts' => $currentContactCrmIds,\n 'new_contacts' => $contactAssociations,\n 'contacts_to_add' => $contactsToAdd,\n 'contacts_to_remove' => $contactsToRemove,\n ]);\n }\n\n private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void\n {\n if (empty($contactsToRemove)) {\n return;\n }\n\n $contactsToDetach = $opportunity->contacts()\n ->whereIn('contacts.crm_provider_id', $contactsToRemove)\n ->pluck('contacts.id')\n ->toArray();\n\n if (! empty($contactsToDetach)) {\n $opportunity->contacts()->detach($contactsToDetach);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_contact_crm_ids' => $contactsToRemove,\n 'removed_contact_count' => count($contactsToDetach),\n ]);\n }\n }\n\n private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void\n {\n if (empty($contactsToAdd)) {\n return;\n }\n\n $contactsAdded = [];\n foreach ($contactsToAdd as $crmId) {\n $id = $contactAssociations[$crmId];\n\n if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {\n $contactsAdded[] = $crmId;\n }\n }\n\n $this->logAddedContacts($opportunity, $contactsAdded);\n }\n\n private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool\n {\n try {\n $contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);\n\n if (! $contact) {\n return false;\n }\n\n return $this->performContactAttachment($opportunity, $contact, $crmId);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [\n 'opportunity_id' => $opportunity->getId(),\n 'contact_crm_id' => $crmId,\n 'error' => $e->getMessage(),\n ]);\n\n return false;\n }\n }\n\n private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool\n {\n try {\n $opportunity->contacts()->attach($contact->getId(), [\n 'crm_provider_id' => $crmId,\n ]);\n\n return true;\n } catch (\\Illuminate\\Database\\QueryException $e) {\n if (str_contains($e->getMessage(), 'Duplicate entry')) {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [\n 'contact_id' => $contact->getId(),\n 'contact_crm_id' => $crmId,\n 'opportunity_id' => $opportunity->getId(),\n ]);\n\n return false;\n }\n\n throw $e;\n }\n }\n\n private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void\n {\n if (! empty($contactsAdded)) {\n $this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'contacts_to_add_count' => count($contactsAdded),\n 'added_contact_crm_ids' => $contactsAdded,\n 'added_contacts_count' => count($contactsAdded),\n ]);\n }\n }\n}","depth":4,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\CollectionResponseAssociatedId;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\Account;\nuse Exception;\nuse Jiminny\\Component\\DealInsights\\Forecast\\Forecast;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Models\\Opportunity;\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Repositories\\Crm\\CrmEntityRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DealFieldsService;\nuse Jiminny\\Services\\Crm\\Hubspot\\OpportunitySyncStrategy\\HubspotSingleSyncStrategy;\nuse Jiminny\\Services\\Crm\\Hubspot\\WebhookSyncBatchProcessor;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Utils\\CurrencyFormatter;\n\n/**\n * Optimized sync methods for better performance\n * These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains\n */\ntrait OpportunitySyncTrait\n{\n private const int BATCH_SIZE = 100;\n private const int BATCH_PROCESS_SIZE = 800;\n\n protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n protected CrmEntityRepository $crmEntityRepository;\n protected DealFieldsService $dealFieldsService;\n\n private ?array $cachedClosedDealStages = null;\n private array $cachedBusinessProcesses = [];\n private array $cachedStages = [];\n\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n $parameters['config'] = $this->config;\n $syncCount = 0;\n $reportedTotal = 0;\n $lastSyncedId = [];\n\n try {\n foreach ($strategies as $strategyName => $syncStrategy) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .\n $strategyName\n );\n\n $total = 0;\n $lastId = null;\n $buffer = [];\n\n // HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies\n foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {\n $buffer[] = $hsOpportunity;\n\n // process every 800 rows (fits < 1 000 association limit)\n if (\\count($buffer) >= self::BATCH_PROCESS_SIZE) {\n $syncCount += $this->processOpportunityBatch($buffer);\n $buffer = [];\n }\n }\n\n // leftovers\n if ($buffer) {\n $syncCount += $this->processOpportunityBatch($buffer);\n }\n\n $reportedTotal += $total;\n $lastSyncedId = $lastId;\n }\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException | CrmException $e) {\n $this->handleSyncException($e, $parameters);\n }\n\n $this->logger->info(\n '[HubSpot] Synced opportunities',\n [\n 'team' => $this->team->getId(),\n 'sync_count' => $syncCount,\n 'total' => $reportedTotal,\n 'last_synced_id' => $lastSyncedId,\n ]\n );\n\n return $reportedTotal;\n }\n\n private function handleSyncException(\\Throwable $e, array $parameters): void\n {\n if (($parameters['since'] ?? null) instanceof Carbon) {\n $parameters['since'] = $parameters['since']->toDateTimeString();\n }\n $parameters['config'] = $this->config->getId();\n\n $this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [\n 'teamId' => $this->team->getUuid(),\n 'parameters' => $parameters,\n 'reason' => $e->getMessage(),\n ]);\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,\n );\n\n $parameters = [\n 'config' => $this->config,\n 'crm_id' => $crmId,\n ];\n\n try {\n if (! $strategy instanceof HubspotSingleSyncStrategy) {\n throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');\n }\n\n $hsOpportunity = $strategy->fetchOpportunity($parameters);\n } catch (\\HubSpot\\Client\\Crm\\Deals\\ApiException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->getUuid(),\n 'crmId' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);\n\n return $this->importOrUpdateOpportunity($hsOpportunity);\n }\n\n /**\n * Process webhook-collected opportunity batches.\n *\n * Drains Redis sets containing company CRM IDs collected from webhook events\n * and dispatches ImportOpportunityBatch jobs for batch processing.\n *\n * @return int Number of opportunity IDs dispatched to jobs\n */\n public function batchSyncOpportunities(): int\n {\n $configId = $this->team->getCrmConfiguration()->getId();\n\n return $this->batchProcessor->processBatchesForObjectType(\n WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,\n $configId\n );\n }\n\n /**\n * Import a batch of opportunities by their CRM IDs.\n * Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().\n *\n * @param array<string> $crmIds HubSpot deal CRM IDs\n *\n * @return array{success: array, failed_ids: array, errors?: array<string, string>}\n */\n public function importOpportunityBatchByIds(array $crmIds): array\n {\n $fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);\n\n $allDeals = [];\n foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {\n $deals = $this->client->getOpportunitiesByIds($chunk, $fields);\n foreach ($deals as $deal) {\n $allDeals[] = $deal;\n }\n }\n\n // IDs not returned by HubSpot are likely deleted or inaccessible deals.\n // These are not failures — retrying won't bring them back.\n $fetchedIds = array_map('strval', array_column($allDeals, 'id'));\n $notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));\n\n if (! empty($notFoundIds)) {\n $this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [\n 'teamId' => $this->team->getId(),\n 'notFoundCount' => \\count($notFoundIds),\n 'notFoundIds' => $notFoundIds,\n 'requestedCount' => \\count($crmIds),\n 'fetchedCount' => \\count($allDeals),\n ]);\n }\n\n if (empty($allDeals)) {\n return ['success' => [], 'failed_ids' => []];\n }\n\n return $this->importOpportunityBatch($allDeals);\n }\n\n private function getClosedDealStages(): array\n {\n if ($this->cachedClosedDealStages !== null) {\n return $this->cachedClosedDealStages;\n }\n\n $stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);\n $data = [\n 'lost' => [],\n 'won' => [],\n ];\n\n foreach ($stages as $stage) {\n if ($stage->probability == 0.00) {\n $data['lost'][] = $stage->crm_provider_id;\n }\n if ($stage->probability == 100.00) {\n $data['won'][] = $stage->crm_provider_id;\n }\n }\n\n $this->cachedClosedDealStages = $data;\n\n return $data;\n }\n\n /**\n * Import deals into the database with pre-fetched associations.\n *\n * API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT\n * caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()\n * where Laravel retries the whole job with backoff. After all retries exhausted,\n * failed() requeues all IDs to Redis.\n *\n * The per-deal loop catches exceptions individually. A deal can end up in three states:\n * - success: imported/updated successfully\n * - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)\n * These are permanent issues — retrying won't fix them.\n * - skipped (null): missing dependencies (no account, unknown pipeline/stage).\n * This is acceptable — the deal cannot be imported until those exist.\n */\n private function importOpportunityBatch(array $deals): array\n {\n $syncedOpportunities = [\n 'success' => [],\n 'failed_ids' => [],\n ];\n $dealIds = array_column($deals, 'id');\n\n // Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the\n // queue job retries the whole batch and eventually requeues all deal IDs back to Redis.\n try {\n $companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');\n $contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');\n\n $associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);\n\n $existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(\n $this->config,\n array_map('strval', $dealIds)\n );\n $existingCrmIdSet = array_flip($existingCrmIds);\n } catch (\\Throwable $e) {\n $this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [\n 'teamId' => $this->team->getId(),\n 'dealCount' => count($dealIds),\n 'error' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n foreach ($deals as $deal) {\n try {\n $deal['associations'] = $this->prepareAssociationsForOpportunity(\n $deal['id'],\n $companyAssociations,\n $contactAssociations,\n $associationsData\n );\n\n $syncedOpportunity = $this->importOrUpdateOpportunity(\n $deal,\n isset($existingCrmIdSet[(string) $deal['id']])\n );\n if ($syncedOpportunity) {\n $syncedOpportunities['success'][] = $syncedOpportunity;\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [\n 'teamId' => $this->team->getId(),\n 'crmId' => $deal['id'],\n 'error' => $e->getMessage(),\n ]);\n $syncedOpportunities['failed_ids'][] = $deal['id'];\n $syncedOpportunities['errors'][$deal['id']] = $e->getMessage();\n }\n }\n\n return $syncedOpportunities;\n }\n\n /**\n * Prepare associated entities for opportunities with optimized batch processing\n * Returns structured data with CRM ID to DB ID mappings for each opportunity\n */\n private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array\n {\n // Step 1: Collect all unique company and contact IDs from associations\n $allCompanyIds = $this->flattenAssociationIds($companyAssociations);\n $allContactIds = $this->flattenAssociationIds($contactAssociations);\n\n // Step 2: Batch sync missing entities and get CRM ID to DB ID mappings\n $companyIdMappings = [];\n $contactIdMappings = [];\n\n if (! empty($allCompanyIds)) {\n $companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);\n }\n\n if (! empty($allContactIds)) {\n $contactIdMappings = $this->prepareAssociatedContacts($allContactIds);\n }\n\n return [\n 'company_id_mappings' => $companyIdMappings,\n 'contact_id_mappings' => $contactIdMappings,\n ];\n }\n\n /**\n * Flatten association data to get unique IDs\n */\n private function flattenAssociationIds(array $associations): array\n {\n $ids = [];\n foreach ($associations as $dealAssociations) {\n if (is_array($dealAssociations)) {\n foreach ($dealAssociations as $id) {\n $ids[$id] = true;\n }\n }\n }\n\n return array_keys($ids);\n }\n\n /**\n * Batch sync missing accounts\n */\n private function prepareAssociatedAccounts(array $companyIds): array\n {\n // Find which accounts already exist\n $existingAccounts = $this->crmEntityRepository\n ->findAccountsByExternalIds($this->config, $companyIds);\n\n $existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();\n\n $existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {\n return [$account->getCrmProviderId() => $account->getId()];\n })->toArray();\n\n $missingCompanyIds = array_diff($companyIds, $existingCompanyIds);\n\n if (empty($missingCompanyIds)) {\n return $existingAccountsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [\n 'teamId' => $this->team->getUuid(),\n 'total_companies' => count($companyIds),\n 'existing_companies' => count($existingCompanyIds),\n 'missing_companies' => count($missingCompanyIds),\n ]);\n\n // we already have limit on opportunity ids count\n // Initialize variable before try block\n $syncedAccountsData = [];\n\n try {\n $syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [\n 'size' => count($missingCompanyIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedAccountsData = [];\n }\n\n return $existingAccountsData + $syncedAccountsData;\n }\n\n /**\n * Prepare associated contacts - find existing and sync missing ones\n * Returns mapping of CRM ID to DB ID\n */\n private function prepareAssociatedContacts(array $contactIds): array\n {\n // Find which contacts already exist\n $existingContacts = $this->crmEntityRepository\n ->findContactsByExternalIds($this->config, $contactIds);\n\n $existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();\n\n // Create mapping for existing contacts\n $existingContactsData = $existingContacts->mapWithKeys(function ($contact) {\n return [$contact->getCrmProviderId() => $contact->getId()];\n })->toArray();\n\n $missingContactIds = array_diff($contactIds, $existingContactIds);\n\n if (empty($missingContactIds)) {\n return $existingContactsData;\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [\n 'teamId' => $this->team->getUuid(),\n 'total_contacts' => count($contactIds),\n 'existing_contacts' => count($existingContactIds),\n 'missing_contacts' => count($missingContactIds),\n ]);\n\n // Sync missing contacts using batch API\n try {\n $syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [\n 'size' => count($missingContactIds),\n 'error' => $e->getMessage(),\n ]);\n $syncedContactsData = [];\n }\n\n return $existingContactsData + $syncedContactsData;\n }\n\n private function batchSyncCrmObjects(string $objectType, array $crmIds): array\n {\n $syncObjects = [];\n $crmObjectIds = array_values($crmIds);\n\n foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {\n try {\n $objects = $objectType === 'companies' ?\n $this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :\n $this->client->getContactsByIds($chunk, $this->getContactFields());\n\n foreach ($objects as $objectId => $objectData) {\n $this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);\n }\n\n $this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [\n 'requested_count' => count($chunk),\n 'synced_count' => count($objects),\n ]);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [\n 'ids' => $chunk,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n return $syncObjects;\n }\n\n private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void\n {\n try {\n $object = $objectType === 'companies' ?\n $this->importAccount($objectData) :\n $this->importContact($objectData);\n\n if ($object) {\n $syncObjects[$object->getCrmProviderId()] = $object->getId();\n }\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [\n 'id' => $objectId,\n 'error' => $e->getMessage(),\n ]);\n }\n }\n\n /**\n * Prepare associations for a single opportunity\n *\n * The return value is an array with the following structure:\n * [\n * 'companies' => [\n * $companyCrmId => $companyId,\n * ...\n * ],\n * 'contacts' => [\n * $contactCrmId => $contactId,\n * ...\n * ],\n * 'account_id' => $accountId,\n * ]\n */\n private function prepareAssociationsForOpportunity(\n string $oppCrmId,\n array $companyAssociations,\n array $contactAssociations,\n array $associationsData\n ): array {\n $associations = [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n\n $oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];\n foreach ($oppCompanyIds as $companyCrmId) {\n if (isset($associationsData['company_id_mappings'][$companyCrmId])) {\n $associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];\n\n // Set primary account (first company becomes primary account)\n if ($associations['account_id'] === null) {\n $associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];\n }\n }\n }\n\n $oppContactIds = $contactAssociations[$oppCrmId] ?? [];\n foreach ($oppContactIds as $contactCrmId) {\n if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {\n $associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];\n }\n }\n\n return $associations;\n }\n\n /**\n * Update only associations for an opportunity\n */\n private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void\n {\n // Update contact associations\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n // Update company (account) associations\n $this->updateOpportunityAccount($opportunity, $associations['account_id']);\n }\n\n /**\n * Remove all contact associations from an opportunity\n */\n private function removeAllOpportunityContacts(Opportunity $opportunity): void\n {\n $currentCount = (int) $opportunity->contacts()->count();\n\n if ($currentCount > 0) {\n $opportunity->contacts()->detach();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_count' => $currentCount,\n ]);\n }\n }\n\n private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void\n {\n if ($accountId === null) {\n // No account ID provided - keep current account\n return;\n }\n\n $currentAccountId = $opportunity->getAccountId();\n\n // Only update if account has changed\n if ($currentAccountId !== $accountId) {\n $opportunity->account_id = $accountId;\n $opportunity->save();\n\n $this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [\n 'opportunity_id' => $opportunity->getId(),\n 'old_account_id' => $currentAccountId,\n 'new_account_id' => $accountId,\n ]);\n }\n }\n\n /**\n * Find existing opportunities by external IDs (OPTIMIZED VERSION)\n * Uses batch query for better performance\n */\n private function findExistingOpportunities(array $crmIds): Collection\n {\n return $this->crmEntityRepository\n ->findOpportunitiesByExternalIds($this->config, $crmIds);\n }\n\n private function processOpportunityBatch(array $opportunities): int\n {\n $syncedOpportunities = $this->importOpportunityBatch($opportunities);\n\n return count($syncedOpportunities['success'] ?? []);\n }\n\n /**\n * Convert single deal associations from HubSpot format to internal format\n * Handles both HubSpot SDK objects and array formats\n *\n * @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed\n *\n * @return array Processed associations with DB IDs\n */\n private function convertDealAssociations(array $opportunityAssociations): array\n {\n $associations = $this->initializeAssociationsStructure();\n\n if (empty($opportunityAssociations)) {\n return $associations;\n }\n\n $associationIds = $this->extractAssociationIds($opportunityAssociations);\n\n $this->processCompanyAssociations($associationIds, $associations);\n $this->processContactAssociations($associationIds, $associations);\n\n return $associations;\n }\n\n private function initializeAssociationsStructure(): array\n {\n return [\n 'companies' => [],\n 'contacts' => [],\n 'account_id' => null, // Primary account for opportunity\n ];\n }\n\n private function extractAssociationIds(array $opportunityAssociations): array\n {\n $associationIds = [];\n\n foreach ($opportunityAssociations as $type => $associationData) {\n if (! empty($associationData)) {\n $associationIds[$type] = $this->convertSingleDealAssociations($associationData);\n }\n }\n\n return $associationIds;\n }\n\n private function processCompanyAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['companies'])) {\n return;\n }\n\n $companyId = $associationIds['companies'][0];\n $account = $this->findOrSyncAccount($companyId);\n\n if ($account instanceof Account) {\n $associations['companies'][$companyId] = $account->getId();\n $associations['account_id'] = $account->getId();\n }\n }\n\n private function processContactAssociations(array $associationIds, array &$associations): void\n {\n if (empty($associationIds['contacts'])) {\n return;\n }\n\n foreach ($associationIds['contacts'] as $contactId) {\n $contact = $this->findOrSyncContact($contactId);\n\n if ($contact instanceof Contact) {\n $associations['contacts'][$contactId] = $contact->getId();\n }\n }\n }\n\n private function findOrSyncAccount(string $companyId): ?Account\n {\n $account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);\n\n if (! $account instanceof Account) {\n $account = $this->syncAccount($companyId);\n }\n\n return $account;\n }\n\n private function findOrSyncContact(string $contactId): ?Contact\n {\n $contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);\n\n if (! $contact instanceof Contact) {\n $contact = $this->syncContact($contactId);\n }\n\n return $contact;\n }\n\n private function convertSingleDealAssociations($opportunityAssociations = null): array\n {\n $associationData = [];\n\n if ($opportunityAssociations === null) {\n return $associationData;\n }\n\n // Handle array input (from extractAssociationIds)\n if (is_array($opportunityAssociations)) {\n return $opportunityAssociations;\n }\n\n // Handle CollectionResponseAssociatedId object\n if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {\n foreach ($opportunityAssociations->getResults() as $association) {\n $associationData[] = $association->getId();\n }\n }\n\n return $associationData;\n }\n\n private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity\n {\n if (empty($crmData['properties'])) {\n return null;\n }\n\n $crmId = (string) $crmData['id'];\n $properties = $crmData['properties'];\n $associations = $crmData['associations'] ?? [];\n\n $opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(\n $this->config,\n $crmId\n );\n\n if ($opportunityExists) {\n return $this->updateOpportunity($crmId, $properties, $associations);\n } else {\n return $this->createOpportunity($crmId, $properties, $associations);\n }\n }\n\n /**\n * Create new opportunity\n */\n private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n if (! $accountId) {\n return null;\n }\n\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n if (! $businessProcess) {\n return null;\n }\n\n $stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);\n if (! $stage) {\n return null;\n }\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->importOpportunityContacts($opportunity, $associations['contacts']);\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n }\n\n /**\n * Update existing opportunity\n */\n private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity\n {\n $accountId = $this->resolveAccountId($associations);\n $businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);\n $stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;\n\n $data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);\n\n $attributes = [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmId,\n ];\n\n $values = array_merge($attributes, $data);\n $opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);\n\n $this->importExternalFieldData($properties, $opportunity->getId());\n $this->updateOpportunityAssociations($opportunity, $associations);\n\n return $opportunity;\n }\n\n private function resolveAccountId(array $associations): ?int\n {\n if (! empty($associations['accountId'])) {\n return $associations['accountId'];\n }\n\n if (empty($associations)) {\n return null;\n }\n\n // we can't resolve multiple account ids (currently SDK returns one company)\n foreach ($associations['companies'] as $accountId) {\n return $accountId;\n }\n\n return null;\n }\n\n private function buildOpportunityData(\n array $properties,\n ?int $accountId,\n ?BusinessProcess $businessProcess,\n ?Stage $stage\n ): array {\n $ownerId = null;\n $profile = null;\n if (! empty($properties['hubspot_owner_id'])) {\n $ownerId = $properties['hubspot_owner_id'];\n $profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);\n }\n\n $name = 'Unknown';\n if (isset($properties['dealname'])) {\n $name = mb_strimwidth($properties['dealname'], 0, 128);\n }\n\n $amount = $this->resolveAmount($properties);\n $currency = $properties['deal_currency_code'] ?? null;\n\n $closeDate = null;\n if (! empty($properties['closedate'])) {\n $closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');\n }\n\n $remotelyCreatedAt = null;\n if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {\n $date = $this->parseCleanDatetime($properties['createdate']);\n $remotelyCreatedAt = $date?->format('Y-m-d H:i:s');\n }\n\n $closedStages = $this->getClosedDealStages();\n $isWon = in_array($properties['dealstage'], $closedStages['won']);\n $isLost = in_array($properties['dealstage'], $closedStages['lost']);\n\n $data = [\n 'team_id' => $this->team->getId(),\n 'user_id' => $profile ? $profile->user_id : null,\n 'owner_id' => $ownerId,\n 'name' => $name,\n 'value' => ! empty($amount) ? $amount : null,\n 'currency_code' => CurrencyFormatter::formatCode($currency),\n 'close_date' => $closeDate,\n 'is_closed' => $isWon || $isLost,\n 'is_won' => $isWon,\n 'remotely_created_at' => $remotelyCreatedAt,\n 'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),\n 'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),\n ];\n\n if ($accountId) {\n $data['account_id'] = $accountId;\n }\n\n if ($stage) {\n $data['stage_id'] = $stage->id;\n }\n\n if ($businessProcess) {\n $recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);\n if ($recordType) {\n $data['record_type_id'] = $recordType->id;\n }\n }\n\n return $data;\n }\n\n private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess\n {\n if ($pipelineId === null) {\n return null;\n }\n\n if (isset($this->cachedBusinessProcesses[$pipelineId])) {\n return $this->cachedBusinessProcesses[$pipelineId];\n }\n\n $businessProcess = $this->getBusinessProcess($pipelineId);\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->importStages();\n $businessProcess = $this->getBusinessProcess($pipelineId);\n }\n\n if (! $businessProcess instanceof BusinessProcess) {\n $this->logger->info(\n '[HubSpot] Deal is not attached to a pipeline',\n [\n 'pipeline' => $pipelineId]\n );\n }\n\n $this->cachedBusinessProcesses[$pipelineId] = $businessProcess;\n\n return $businessProcess;\n }\n\n private function getBusinessProcess(string $pipelineId): ?BusinessProcess\n {\n return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);\n }\n\n private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage\n {\n if (empty($stageId)) {\n return null;\n }\n\n $cacheKey = $businessProcess->getId() . ':' . $stageId;\n if (isset($this->cachedStages[$cacheKey])) {\n return $this->cachedStages[$cacheKey];\n }\n\n $stage = $this->crmEntityRepository->getPipelineStageByConditions(\n $businessProcess,\n [\n 'crm_provider_id' => $stageId,\n 'type' => Stage::TYPE_OPPORTUNITY,\n ]\n );\n\n if ($stage === null) {\n $this->importStages(null, $stageId);\n }\n\n if ($stage === null) {\n $this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);\n }\n\n $this->cachedStages[$cacheKey] = $stage;\n\n return $stage;\n }\n\n private function resolveAmount(array $properties): ?string\n {\n $amount = null;\n if (! empty($properties['amount'])) {\n $amount = str_replace(',', '', $properties['amount']);\n }\n\n if ($this->config->hasDefaultCurrencyFieldSet()) {\n $valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();\n $amount = $properties[$valueFieldName] ?? $amount;\n }\n\n return $amount;\n }\n\n private function parseCleanDatetime(string $datetime): ?Carbon\n {\n // Treat pre-1980 values as invalid\n $minValidDate = Carbon::parse('1980-01-01 00:00:00');\n\n try {\n $date = Carbon::parse($datetime);\n\n if ($minValidDate->gt($date)) {\n return null;\n }\n\n return $date;\n } catch (Exception) {\n return null; // On parse error, treat as null\n }\n }\n\n private function resolveDealProbability(?string $stageProbability): int\n {\n if ($stageProbability === null) {\n return 0;\n }\n\n $probability = (float) $stageProbability;\n\n return $probability > 1 ? 0 : (int) ($probability * 100);\n }\n\n private function resolveForecastCategory(?string $forecastCategory): string\n {\n if (! $forecastCategory) {\n return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;\n }\n\n $forecastCategory = str_replace('_', ' ', $forecastCategory);\n\n return ucwords(strtolower($forecastCategory));\n }\n\n private function importExternalFieldData(array $properties, int $opportunityId): void\n {\n $crmFields = $this->getOpportunitySyncableFields();\n $this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);\n }\n\n private function importOpportunityContacts(Opportunity $opportunity, array $associations): void\n {\n // Handle empty or missing contact associations\n if (empty($associations)) {\n // Remove all existing contact associations if none provided\n $this->removeAllOpportunityContacts($opportunity);\n\n return;\n }\n\n // Use differential sync approach for better performance and accuracy\n $this->syncOpportunityContactsDifferential($opportunity, $associations);\n }\n\n /**\n * Sync opportunity contacts using differential approach\n * This compares current vs new associations and only makes necessary changes\n */\n private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void\n {\n $currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);\n $contactAssociationIds = array_keys($contactAssociations);\n\n $contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);\n $contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);\n\n if (empty($contactsToAdd) && empty($contactsToRemove)) {\n return;\n }\n\n $this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);\n\n $this->removeContactAssociations($opportunity, $contactsToRemove);\n $this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);\n }\n\n private function getCurrentContactCrmIds(Opportunity $opportunity): array\n {\n return $opportunity->contacts()\n ->pluck('contacts.crm_provider_id')\n ->toArray();\n }\n\n private function logContactAssociationChanges(\n Opportunity $opportunity,\n array $currentContactCrmIds,\n array $contactAssociations,\n array $contactsToAdd,\n array $contactsToRemove\n ): void {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [\n 'opportunity_id' => $opportunity->getId(),\n 'current_contacts' => $currentContactCrmIds,\n 'new_contacts' => $contactAssociations,\n 'contacts_to_add' => $contactsToAdd,\n 'contacts_to_remove' => $contactsToRemove,\n ]);\n }\n\n private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void\n {\n if (empty($contactsToRemove)) {\n return;\n }\n\n $contactsToDetach = $opportunity->contacts()\n ->whereIn('contacts.crm_provider_id', $contactsToRemove)\n ->pluck('contacts.id')\n ->toArray();\n\n if (! empty($contactsToDetach)) {\n $opportunity->contacts()->detach($contactsToDetach);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'removed_contact_crm_ids' => $contactsToRemove,\n 'removed_contact_count' => count($contactsToDetach),\n ]);\n }\n }\n\n private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void\n {\n if (empty($contactsToAdd)) {\n return;\n }\n\n $contactsAdded = [];\n foreach ($contactsToAdd as $crmId) {\n $id = $contactAssociations[$crmId];\n\n if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {\n $contactsAdded[] = $crmId;\n }\n }\n\n $this->logAddedContacts($opportunity, $contactsAdded);\n }\n\n private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool\n {\n try {\n $contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);\n\n if (! $contact) {\n return false;\n }\n\n return $this->performContactAttachment($opportunity, $contact, $crmId);\n } catch (\\Throwable $e) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [\n 'opportunity_id' => $opportunity->getId(),\n 'contact_crm_id' => $crmId,\n 'error' => $e->getMessage(),\n ]);\n\n return false;\n }\n }\n\n private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool\n {\n try {\n $opportunity->contacts()->attach($contact->getId(), [\n 'crm_provider_id' => $crmId,\n ]);\n\n return true;\n } catch (\\Illuminate\\Database\\QueryException $e) {\n if (str_contains($e->getMessage(), 'Duplicate entry')) {\n $this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [\n 'contact_id' => $contact->getId(),\n 'contact_crm_id' => $crmId,\n 'opportunity_id' => $opportunity->getId(),\n ]);\n\n return false;\n }\n\n throw $e;\n }\n }\n\n private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void\n {\n if (! empty($contactsAdded)) {\n $this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [\n 'opportunity_id' => $opportunity->getId(),\n 'contacts_to_add_count' => count($contactsAdded),\n 'added_contact_crm_ids' => $contactsAdded,\n 'added_contacts_count' => count($contactsAdded),\n ]);\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.049609374,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.23320313,"top":1.0,"width":0.01015625,"height":0.0},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.69921875,"top":0.10902778,"width":0.00859375,"height":0.013194445},"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7097656,"top":0.10763889,"width":0.00859375,"height":0.015972223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.71835935,"top":0.10763889,"width":0.008203125,"height":0.015972223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<template>\n <WelcomeLayout\n title=\"Account disconnected\"\n textPosition=\"center\"\n :icon=\"faUnlink\"\n :class=\"$style.layout\"\n >\n <div :class=\"$style.container\" v-if=\"providersLoaded\">\n <p>\n <strong>\n It looks like your {{ localProvider.displayName }} account has become\n disconnected\n </strong>\n </p>\n <p :class=\"$style.small\">Please re-connect to continue</p>\n <p v-if=\"isInIframe\">\n We'll open the {{ localProvider.displayName }} authentication in a new\n tab. Please return here and refresh the page once complete\n </p>\n\n <GoogleLikeButton\n v-if=\"localProvider.viaIntegrationApp && crmTokenLoaded\"\n as=\"a\"\n :key=\"localProvider.name\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n @click=\"integrationAppOnClick\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n <GoogleLikeButton\n v-if=\"!localProvider.viaIntegrationApp\"\n as=\"a\"\n :key=\"localProvider.name\"\n :href=\"`/auth/redirect/${localProvider.name}`\"\n :target=\"target\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n </div>\n <BuildInfo />\n\n <KioskBanner />\n </WelcomeLayout>\n</template>\n\n<script>\nimport window from \"window\";\nimport axios from \"axios\";\nimport { faUnlink } from \"@fortawesome/pro-regular-svg-icons\";\nimport isInIframe from \"@/utils/isInIframe\";\nimport BuildInfo from \"@/components/layout/BuildInfo/BuildInfo.vue\";\nimport KioskBanner from \"@/components/shared/KioskBanner/KioskBanner.vue\";\nimport WelcomeLayout from \"@/components/layout/WelcomeLayout/WelcomeLayout.vue\";\nimport GoogleLikeButton from \"@/components/shared/Buttons/GoogleLikeButton.vue\";\nimport { showSnackbarError, normalizeError } from \"@/utils/index\";\nimport { IntegrationAppClient } from \"@integration-app/sdk\";\n\nexport default {\n name: \"ConnectPage\",\n components: {\n BuildInfo,\n KioskBanner,\n WelcomeLayout,\n GoogleLikeButton,\n },\n data() {\n return {\n ...window.connectData,\n crmToken: null,\n faUnlink,\n isInIframe,\n providers: [],\n providersLoaded: false,\n crmTokenLoaded: false,\n };\n },\n computed: {\n localProvider() {\n return this.providers.find((e) => e.name === this.provider);\n },\n target() {\n return this.isInIframe ? \"_blank\" : null;\n },\n },\n created() {\n this.getProviders();\n },\n mounted() {\n this.showErrors();\n },\n watch: {\n providersLoaded() {\n if (this.providersLoaded) {\n this.prepareIntegrationAppConnection();\n }\n },\n },\n methods: {\n showErrors() {\n if (!this.error) return;\n\n showSnackbarError(this.error, undefined, undefined, false);\n },\n unwrapEntityResponse({ data }) {\n return data.map(({ icon, name, displayName, viaIntegrationApp }) => {\n return { icon, name, displayName, viaIntegrationApp };\n });\n },\n async getProviders() {\n try {\n const response = await axios.get(\"/api/v1/connect-providers\");\n this.providers = this.unwrapEntityResponse(response);\n this.providersLoaded = true;\n } catch {\n showSnackbarError(\n \"An error occurred, while loading form data (connect providers).\",\n );\n }\n },\n async prepareIntegrationAppConnection() {\n if (this.localProvider.viaIntegrationApp) {\n try {\n const response = await axios.get(\"/api/v1/integration-app-token\");\n this.crmToken = response.data.token;\n this.crmTokenLoaded = true;\n } catch (error) {\n console.log(error);\n showSnackbarError(\n `An error occurred while preparing the page.\n Try refreshing, if the error persists get in touch with the Jiminny team.`,\n );\n }\n }\n },\n async integrationAppOnClick() {\n console.log('[IntegrationApp] integrationAppOnClick called');\n const integrationApp = new IntegrationAppClient({\n token: this.crmToken,\n });\n\n const connection = await integrationApp\n .integration(this.localProvider.name)\n .openNewConnection({\n showPoweredBy: false,\n allowMultipleConnections: false,\n }).catch((err) => {\n console.log('[IntegrationApp] openNewConnection rejected:', err);\n return null;\n });\n\n console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));\n\n // [IntegrationApp] openNewConnection resolved: {\n // \"id\":\"69e0b41a67d0068c2ca0b48e\",\n // \"name\":\"Zoho CRM\",\n // \"userId\":\"1ece66c8-feb1-4df1-b321-21607daf4623\",\n // \"tenantId\":\"69e0b3faef3e7b6248189289\",\n // \"isTest\":false,\n // \"connected\":true,\n // \"state\":\"READY\",\n // \"errors\":[],\n // \"integrationId\":\"66fe6c913202f3a165e3c14d\",\n // \"externalAppId\":\"6671653e7e2d642e4e41b0fa\",\n // \"authOptionKey\":\"\",\n // \"createdAt\":\"2026-04-16T10:04:10.420Z\",\n // \"updatedAt\":\"2026-04-16T10:04:10.575Z\",\n // \"retryAttempts\":0,\n // \"isDeactivated\":false\n // }\n\n if (connection && connection.disconnected !== true && connection.connected !== false) {\n console.log('[IntegrationApp] connection condition matched');\n try {\n const saveRequest = await axios.post(\n \"/api/v1/integration-app-connect\",\n );\n if (saveRequest.data && saveRequest.data.success === true) {\n /** If all is good refresh the page here */\n window.location = \"/dashboard\";\n return;\n }\n\n throw new Error(saveRequest.data.message);\n } catch (error) {\n console.log(error);\n showSnackbarError(normalizeError(error));\n }\n }\n },\n },\n};\n</script>\n\n<style module lang=\"less\" src=\"./connect.less\"></style>","depth":4,"value":"<template>\n <WelcomeLayout\n title=\"Account disconnected\"\n textPosition=\"center\"\n :icon=\"faUnlink\"\n :class=\"$style.layout\"\n >\n <div :class=\"$style.container\" v-if=\"providersLoaded\">\n <p>\n <strong>\n It looks like your {{ localProvider.displayName }} account has become\n disconnected\n </strong>\n </p>\n <p :class=\"$style.small\">Please re-connect to continue</p>\n <p v-if=\"isInIframe\">\n We'll open the {{ localProvider.displayName }} authentication in a new\n tab. Please return here and refresh the page once complete\n </p>\n\n <GoogleLikeButton\n v-if=\"localProvider.viaIntegrationApp && crmTokenLoaded\"\n as=\"a\"\n :key=\"localProvider.name\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n @click=\"integrationAppOnClick\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n <GoogleLikeButton\n v-if=\"!localProvider.viaIntegrationApp\"\n as=\"a\"\n :key=\"localProvider.name\"\n :href=\"`/auth/redirect/${localProvider.name}`\"\n :target=\"target\"\n :brand-logo=\"localProvider.name\"\n :class=\"$style.connectButton\"\n >\n Sign in with {{ localProvider.displayName }}\n </GoogleLikeButton>\n </div>\n <BuildInfo />\n\n <KioskBanner />\n </WelcomeLayout>\n</template>\n\n<script>\nimport window from \"window\";\nimport axios from \"axios\";\nimport { faUnlink } from \"@fortawesome/pro-regular-svg-icons\";\nimport isInIframe from \"@/utils/isInIframe\";\nimport BuildInfo from \"@/components/layout/BuildInfo/BuildInfo.vue\";\nimport KioskBanner from \"@/components/shared/KioskBanner/KioskBanner.vue\";\nimport WelcomeLayout from \"@/components/layout/WelcomeLayout/WelcomeLayout.vue\";\nimport GoogleLikeButton from \"@/components/shared/Buttons/GoogleLikeButton.vue\";\nimport { showSnackbarError, normalizeError } from \"@/utils/index\";\nimport { IntegrationAppClient } from \"@integration-app/sdk\";\n\nexport default {\n name: \"ConnectPage\",\n components: {\n BuildInfo,\n KioskBanner,\n WelcomeLayout,\n GoogleLikeButton,\n },\n data() {\n return {\n ...window.connectData,\n crmToken: null,\n faUnlink,\n isInIframe,\n providers: [],\n providersLoaded: false,\n crmTokenLoaded: false,\n };\n },\n computed: {\n localProvider() {\n return this.providers.find((e) => e.name === this.provider);\n },\n target() {\n return this.isInIframe ? \"_blank\" : null;\n },\n },\n created() {\n this.getProviders();\n },\n mounted() {\n this.showErrors();\n },\n watch: {\n providersLoaded() {\n if (this.providersLoaded) {\n this.prepareIntegrationAppConnection();\n }\n },\n },\n methods: {\n showErrors() {\n if (!this.error) return;\n\n showSnackbarError(this.error, undefined, undefined, false);\n },\n unwrapEntityResponse({ data }) {\n return data.map(({ icon, name, displayName, viaIntegrationApp }) => {\n return { icon, name, displayName, viaIntegrationApp };\n });\n },\n async getProviders() {\n try {\n const response = await axios.get(\"/api/v1/connect-providers\");\n this.providers = this.unwrapEntityResponse(response);\n this.providersLoaded = true;\n } catch {\n showSnackbarError(\n \"An error occurred, while loading form data (connect providers).\",\n );\n }\n },\n async prepareIntegrationAppConnection() {\n if (this.localProvider.viaIntegrationApp) {\n try {\n const response = await axios.get(\"/api/v1/integration-app-token\");\n this.crmToken = response.data.token;\n this.crmTokenLoaded = true;\n } catch (error) {\n console.log(error);\n showSnackbarError(\n `An error occurred while preparing the page.\n Try refreshing, if the error persists get in touch with the Jiminny team.`,\n );\n }\n }\n },\n async integrationAppOnClick() {\n console.log('[IntegrationApp] integrationAppOnClick called');\n const integrationApp = new IntegrationAppClient({\n token: this.crmToken,\n });\n\n const connection = await integrationApp\n .integration(this.localProvider.name)\n .openNewConnection({\n showPoweredBy: false,\n allowMultipleConnections: false,\n }).catch((err) => {\n console.log('[IntegrationApp] openNewConnection rejected:', err);\n return null;\n });\n\n console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));\n\n // [IntegrationApp] openNewConnection resolved: {\n // \"id\":\"69e0b41a67d0068c2ca0b48e\",\n // \"name\":\"Zoho CRM\",\n // \"userId\":\"1ece66c8-feb1-4df1-b321-21607daf4623\",\n // \"tenantId\":\"69e0b3faef3e7b6248189289\",\n // \"isTest\":false,\n // \"connected\":true,\n // \"state\":\"READY\",\n // \"errors\":[],\n // \"integrationId\":\"66fe6c913202f3a165e3c14d\",\n // \"externalAppId\":\"6671653e7e2d642e4e41b0fa\",\n // \"authOptionKey\":\"\",\n // \"createdAt\":\"2026-04-16T10:04:10.420Z\",\n // \"updatedAt\":\"2026-04-16T10:04:10.575Z\",\n // \"retryAttempts\":0,\n // \"isDeactivated\":false\n // }\n\n if (connection && connection.disconnected !== true && connection.connected !== false) {\n console.log('[IntegrationApp] connection condition matched');\n try {\n const saveRequest = await axios.post(\n \"/api/v1/integration-app-connect\",\n );\n if (saveRequest.data && saveRequest.data.success === true) {\n /** If all is good refresh the page here */\n window.location = \"/dashboard\";\n return;\n }\n\n throw new Error(saveRequest.data.message);\n } catch (error) {\n console.log(error);\n showSnackbarError(normalizeError(error));\n }\n }\n },\n },\n};\n</script>\n\n<style module lang=\"less\" src=\"./connect.less\"></style>","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
8951690351009007186
|
-8754547338898009690
|
idle
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
Replace
New Line
Preserve case
2/4
Previous Occurrence
Next Occurrence
Filter Search Results
Open in Window, Multiple Cursors
Click to highlight
Close
Code changed:
Hide
Sync Changes
Hide This Notification
33
2
19
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use HubSpot\Client\Crm\Deals\Model\CollectionResponseAssociatedId;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\Account;
use Exception;
use Jiminny\Component\DealInsights\Forecast\Forecast;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Contact;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Exceptions\CrmException;
use Jiminny\Models\Opportunity;
use Illuminate\Support\Collection;
use Jiminny\Models\Stage;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Services\Crm\Hubspot\DealFieldsService;
use Jiminny\Services\Crm\Hubspot\OpportunitySyncStrategy\HubspotSingleSyncStrategy;
use Jiminny\Services\Crm\Hubspot\WebhookSyncBatchProcessor;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Utils\CurrencyFormatter;
/**
* Optimized sync methods for better performance
* These methods can be integrated into SyncCrmEntitiesTrait for significant performance gains
*/
trait OpportunitySyncTrait
{
private const int BATCH_SIZE = 100;
private const int BATCH_PROCESS_SIZE = 800;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected DealFieldsService $dealFieldsService;
private ?array $cachedClosedDealStages = null;
private array $cachedBusinessProcesses = [];
private array $cachedStages = [];
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$parameters['config'] = $this->config;
$syncCount = 0;
$reportedTotal = 0;
$lastSyncedId = [];
try {
foreach ($strategies as $strategyName => $syncStrategy) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Syncing opportunities using strategy: ' .
$strategyName
);
$total = 0;
$lastId = null;
$buffer = [];
// HubspotWebhookBatchSyncStrategy returns empty generator, this is for other strategies
foreach ($syncStrategy->fetchOpportunities($parameters, $total, $lastId) as $hsOpportunity) {
$buffer[] = $hsOpportunity;
// process every 800 rows (fits < 1 000 association limit)
if (\count($buffer) >= self::BATCH_PROCESS_SIZE) {
$syncCount += $this->processOpportunityBatch($buffer);
$buffer = [];
}
}
// leftovers
if ($buffer) {
$syncCount += $this->processOpportunityBatch($buffer);
}
$reportedTotal += $total;
$lastSyncedId = $lastId;
}
} catch (\HubSpot\Client\Crm\Deals\ApiException | CrmException $e) {
$this->handleSyncException($e, $parameters);
}
$this->logger->info(
'[HubSpot] Synced opportunities',
[
'team' => $this->team->getId(),
'sync_count' => $syncCount,
'total' => $reportedTotal,
'last_synced_id' => $lastSyncedId,
]
);
return $reportedTotal;
}
private function handleSyncException(\Throwable $e, array $parameters): void
{
if (($parameters['since'] ?? null) instanceof Carbon) {
$parameters['since'] = $parameters['since']->toDateTimeString();
}
$parameters['config'] = $this->config->getId();
$this->logger->warning('[' . $this->getDisplayName() . '] Sync opportunities failed', [
'teamId' => $this->team->getUuid(),
'parameters' => $parameters,
'reason' => $e->getMessage(),
]);
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY,
);
$parameters = [
'config' => $this->config,
'crm_id' => $crmId,
];
try {
if (! $strategy instanceof HubspotSingleSyncStrategy) {
throw new InvalidArgumentException('Strategy must by HubspotSingleSyncStrategy');
}
$hsOpportunity = $strategy->fetchOpportunity($parameters);
} catch (\HubSpot\Client\Crm\Deals\ApiException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->getUuid(),
'crmId' => $crmId,
'reason' => $e->getMessage(),
]);
return null;
}
$hsOpportunity['associations'] = $this->convertDealAssociations($hsOpportunity['associations'] ?? []);
return $this->importOrUpdateOpportunity($hsOpportunity);
}
/**
* Process webhook-collected opportunity batches.
*
* Drains Redis sets containing company CRM IDs collected from webhook events
* and dispatches ImportOpportunityBatch jobs for batch processing.
*
* @return int Number of opportunity IDs dispatched to jobs
*/
public function batchSyncOpportunities(): int
{
$configId = $this->team->getCrmConfiguration()->getId();
return $this->batchProcessor->processBatchesForObjectType(
WebhookSyncBatchProcessor::OBJECT_TYPE_DEAL,
$configId
);
}
/**
* Import a batch of opportunities by their CRM IDs.
* Fetches opportunity data from HubSpot API and delegates to importOpportunityBatch().
*
* @param array<string> $crmIds HubSpot deal CRM IDs
*
* @return array{success: array, failed_ids: array, errors?: array<string, string>}
*/
public function importOpportunityBatchByIds(array $crmIds): array
{
$fields = $this->dealFieldsService->getFieldsForConfiguration($this->config);
$allDeals = [];
foreach (array_chunk($crmIds, self::BATCH_SIZE) as $chunk) {
$deals = $this->client->getOpportunitiesByIds($chunk, $fields);
foreach ($deals as $deal) {
$allDeals[] = $deal;
}
}
// IDs not returned by HubSpot are likely deleted or inaccessible deals.
// These are not failures — retrying won't bring them back.
$fetchedIds = array_map('strval', array_column($allDeals, 'id'));
$notFoundIds = array_values(array_diff(array_map('strval', $crmIds), $fetchedIds));
if (! empty($notFoundIds)) {
$this->logger->info('[' . $this->getDisplayName() . '] CRM IDs not found in HubSpot (likely deleted)', [
'teamId' => $this->team->getId(),
'notFoundCount' => \count($notFoundIds),
'notFoundIds' => $notFoundIds,
'requestedCount' => \count($crmIds),
'fetchedCount' => \count($allDeals),
]);
}
if (empty($allDeals)) {
return ['success' => [], 'failed_ids' => []];
}
return $this->importOpportunityBatch($allDeals);
}
private function getClosedDealStages(): array
{
if ($this->cachedClosedDealStages !== null) {
return $this->cachedClosedDealStages;
}
$stages = $this->crmEntityRepository->getOpportunityClosedStages($this->config);
$data = [
'lost' => [],
'won' => [],
];
foreach ($stages as $stage) {
if ($stage->probability == 0.00) {
$data['lost'][] = $stage->crm_provider_id;
}
if ($stage->probability == 100.00) {
$data['won'][] = $stage->crm_provider_id;
}
}
$this->cachedClosedDealStages = $data;
return $data;
}
/**
* Import deals into the database with pre-fetched associations.
*
* API calls here (getAssociationsData, getExistingOpportunityCrmIds) are NOT
* caught — if they throw, the exception propagates to ImportOpportunityBatch::handle()
* where Laravel retries the whole job with backoff. After all retries exhausted,
* failed() requeues all IDs to Redis.
*
* The per-deal loop catches exceptions individually. A deal can end up in three states:
* - success: imported/updated successfully
* - failed_ids: exception thrown (DB constraint violation, corrupt data, etc.)
* These are permanent issues — retrying won't fix them.
* - skipped (null): missing dependencies (no account, unknown pipeline/stage).
* This is acceptable — the deal cannot be imported until those exist.
*/
private function importOpportunityBatch(array $deals): array
{
$syncedOpportunities = [
'success' => [],
'failed_ids' => [],
];
$dealIds = array_column($deals, 'id');
// Shared association/existing-ID preparation is batch-level state. If it fails, rethrow so the
// queue job retries the whole batch and eventually requeues all deal IDs back to Redis.
try {
$companyAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'companies');
$contactAssociations = $this->client->getAssociationsData($dealIds, 'deals', 'contacts');
$associationsData = $this->prepareAssociatedEntities($companyAssociations, $contactAssociations);
$existingCrmIds = $this->crmEntityRepository->getExistingOpportunityCrmIds(
$this->config,
array_map('strval', $dealIds)
);
$existingCrmIdSet = array_flip($existingCrmIds);
} catch (\Throwable $e) {
$this->logger->error('[' . $this->getDisplayName() . '] Failed to fetch associations or existing IDs', [
'teamId' => $this->team->getId(),
'dealCount' => count($dealIds),
'error' => $e->getMessage(),
]);
throw $e;
}
foreach ($deals as $deal) {
try {
$deal['associations'] = $this->prepareAssociationsForOpportunity(
$deal['id'],
$companyAssociations,
$contactAssociations,
$associationsData
);
$syncedOpportunity = $this->importOrUpdateOpportunity(
$deal,
isset($existingCrmIdSet[(string) $deal['id']])
);
if ($syncedOpportunity) {
$syncedOpportunities['success'][] = $syncedOpportunity;
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import opportunity', [
'teamId' => $this->team->getId(),
'crmId' => $deal['id'],
'error' => $e->getMessage(),
]);
$syncedOpportunities['failed_ids'][] = $deal['id'];
$syncedOpportunities['errors'][$deal['id']] = $e->getMessage();
}
}
return $syncedOpportunities;
}
/**
* Prepare associated entities for opportunities with optimized batch processing
* Returns structured data with CRM ID to DB ID mappings for each opportunity
*/
private function prepareAssociatedEntities(array $companyAssociations, array $contactAssociations): array
{
// Step 1: Collect all unique company and contact IDs from associations
$allCompanyIds = $this->flattenAssociationIds($companyAssociations);
$allContactIds = $this->flattenAssociationIds($contactAssociations);
// Step 2: Batch sync missing entities and get CRM ID to DB ID mappings
$companyIdMappings = [];
$contactIdMappings = [];
if (! empty($allCompanyIds)) {
$companyIdMappings = $this->prepareAssociatedAccounts($allCompanyIds);
}
if (! empty($allContactIds)) {
$contactIdMappings = $this->prepareAssociatedContacts($allContactIds);
}
return [
'company_id_mappings' => $companyIdMappings,
'contact_id_mappings' => $contactIdMappings,
];
}
/**
* Flatten association data to get unique IDs
*/
private function flattenAssociationIds(array $associations): array
{
$ids = [];
foreach ($associations as $dealAssociations) {
if (is_array($dealAssociations)) {
foreach ($dealAssociations as $id) {
$ids[$id] = true;
}
}
}
return array_keys($ids);
}
/**
* Batch sync missing accounts
*/
private function prepareAssociatedAccounts(array $companyIds): array
{
// Find which accounts already exist
$existingAccounts = $this->crmEntityRepository
->findAccountsByExternalIds($this->config, $companyIds);
$existingCompanyIds = $existingAccounts->pluck('crm_provider_id')->toArray();
$existingAccountsData = $existingAccounts->mapWithKeys(function ($account) {
return [$account->getCrmProviderId() => $account->getId()];
})->toArray();
$missingCompanyIds = array_diff($companyIds, $existingCompanyIds);
if (empty($missingCompanyIds)) {
return $existingAccountsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing accounts', [
'teamId' => $this->team->getUuid(),
'total_companies' => count($companyIds),
'existing_companies' => count($existingCompanyIds),
'missing_companies' => count($missingCompanyIds),
]);
// we already have limit on opportunity ids count
// Initialize variable before try block
$syncedAccountsData = [];
try {
$syncedAccountsData = $this->batchSyncCrmObjects('companies', $missingCompanyIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing accounts', [
'size' => count($missingCompanyIds),
'error' => $e->getMessage(),
]);
$syncedAccountsData = [];
}
return $existingAccountsData + $syncedAccountsData;
}
/**
* Prepare associated contacts - find existing and sync missing ones
* Returns mapping of CRM ID to DB ID
*/
private function prepareAssociatedContacts(array $contactIds): array
{
// Find which contacts already exist
$existingContacts = $this->crmEntityRepository
->findContactsByExternalIds($this->config, $contactIds);
$existingContactIds = $existingContacts->pluck('crm_provider_id')->toArray();
// Create mapping for existing contacts
$existingContactsData = $existingContacts->mapWithKeys(function ($contact) {
return [$contact->getCrmProviderId() => $contact->getId()];
})->toArray();
$missingContactIds = array_diff($contactIds, $existingContactIds);
if (empty($missingContactIds)) {
return $existingContactsData;
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch syncing missing contacts', [
'teamId' => $this->team->getUuid(),
'total_contacts' => count($contactIds),
'existing_contacts' => count($existingContactIds),
'missing_contacts' => count($missingContactIds),
]);
// Sync missing contacts using batch API
try {
$syncedContactsData = $this->batchSyncCrmObjects('contacts', $missingContactIds);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to sync missing contacts', [
'size' => count($missingContactIds),
'error' => $e->getMessage(),
]);
$syncedContactsData = [];
}
return $existingContactsData + $syncedContactsData;
}
private function batchSyncCrmObjects(string $objectType, array $crmIds): array
{
$syncObjects = [];
$crmObjectIds = array_values($crmIds);
foreach (array_chunk($crmObjectIds, self::BATCH_SIZE) as $chunk) {
try {
$objects = $objectType === 'companies' ?
$this->client->getCompaniesByIds($chunk, $this->getCompanyFields()) :
$this->client->getContactsByIds($chunk, $this->getContactFields());
foreach ($objects as $objectId => $objectData) {
$this->importCrmObject($objectType, (string) $objectId, $objectData, $syncObjects);
}
$this->logger->info('[' . $this->getDisplayName() . '] Batch synced ' . $objectType, [
'requested_count' => count($chunk),
'synced_count' => count($objects),
]);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Batch ' . $objectType . ' sync failed', [
'ids' => $chunk,
'error' => $e->getMessage(),
]);
}
}
return $syncObjects;
}
private function importCrmObject(string $objectType, string $objectId, mixed $objectData, array &$syncObjects): void
{
try {
$object = $objectType === 'companies' ?
$this->importAccount($objectData) :
$this->importContact($objectData);
if ($object) {
$syncObjects[$object->getCrmProviderId()] = $object->getId();
}
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to import batch ' . $objectType, [
'id' => $objectId,
'error' => $e->getMessage(),
]);
}
}
/**
* Prepare associations for a single opportunity
*
* The return value is an array with the following structure:
* [
* 'companies' => [
* $companyCrmId => $companyId,
* ...
* ],
* 'contacts' => [
* $contactCrmId => $contactId,
* ...
* ],
* 'account_id' => $accountId,
* ]
*/
private function prepareAssociationsForOpportunity(
string $oppCrmId,
array $companyAssociations,
array $contactAssociations,
array $associationsData
): array {
$associations = [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
$oppCompanyIds = $companyAssociations[$oppCrmId] ?? [];
foreach ($oppCompanyIds as $companyCrmId) {
if (isset($associationsData['company_id_mappings'][$companyCrmId])) {
$associations['companies'][$companyCrmId] = $associationsData['company_id_mappings'][$companyCrmId];
// Set primary account (first company becomes primary account)
if ($associations['account_id'] === null) {
$associations['account_id'] = $associationsData['company_id_mappings'][$companyCrmId];
}
}
}
$oppContactIds = $contactAssociations[$oppCrmId] ?? [];
foreach ($oppContactIds as $contactCrmId) {
if (isset($associationsData['contact_id_mappings'][$contactCrmId])) {
$associations['contacts'][$contactCrmId] = $associationsData['contact_id_mappings'][$contactCrmId];
}
}
return $associations;
}
/**
* Update only associations for an opportunity
*/
private function updateOpportunityAssociations(Opportunity $opportunity, array $associations): void
{
// Update contact associations
$this->importOpportunityContacts($opportunity, $associations['contacts']);
// Update company (account) associations
$this->updateOpportunityAccount($opportunity, $associations['account_id']);
}
/**
* Remove all contact associations from an opportunity
*/
private function removeAllOpportunityContacts(Opportunity $opportunity): void
{
$currentCount = (int) $opportunity->contacts()->count();
if ($currentCount > 0) {
$opportunity->contacts()->detach();
$this->logger->info('[' . $this->getDisplayName() . '] Removed all contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_count' => $currentCount,
]);
}
}
private function updateOpportunityAccount(Opportunity $opportunity, ?int $accountId): void
{
if ($accountId === null) {
// No account ID provided - keep current account
return;
}
$currentAccountId = $opportunity->getAccountId();
// Only update if account has changed
if ($currentAccountId !== $accountId) {
$opportunity->account_id = $accountId;
$opportunity->save();
$this->logger->info('[' . $this->getDisplayName() . '] Updated opportunity account association', [
'opportunity_id' => $opportunity->getId(),
'old_account_id' => $currentAccountId,
'new_account_id' => $accountId,
]);
}
}
/**
* Find existing opportunities by external IDs (OPTIMIZED VERSION)
* Uses batch query for better performance
*/
private function findExistingOpportunities(array $crmIds): Collection
{
return $this->crmEntityRepository
->findOpportunitiesByExternalIds($this->config, $crmIds);
}
private function processOpportunityBatch(array $opportunities): int
{
$syncedOpportunities = $this->importOpportunityBatch($opportunities);
return count($syncedOpportunities['success'] ?? []);
}
/**
* Convert single deal associations from HubSpot format to internal format
* Handles both HubSpot SDK objects and array formats
*
* @param array $opportunityAssociations Raw associations from HubSpot API or pre-processed
*
* @return array Processed associations with DB IDs
*/
private function convertDealAssociations(array $opportunityAssociations): array
{
$associations = $this->initializeAssociationsStructure();
if (empty($opportunityAssociations)) {
return $associations;
}
$associationIds = $this->extractAssociationIds($opportunityAssociations);
$this->processCompanyAssociations($associationIds, $associations);
$this->processContactAssociations($associationIds, $associations);
return $associations;
}
private function initializeAssociationsStructure(): array
{
return [
'companies' => [],
'contacts' => [],
'account_id' => null, // Primary account for opportunity
];
}
private function extractAssociationIds(array $opportunityAssociations): array
{
$associationIds = [];
foreach ($opportunityAssociations as $type => $associationData) {
if (! empty($associationData)) {
$associationIds[$type] = $this->convertSingleDealAssociations($associationData);
}
}
return $associationIds;
}
private function processCompanyAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['companies'])) {
return;
}
$companyId = $associationIds['companies'][0];
$account = $this->findOrSyncAccount($companyId);
if ($account instanceof Account) {
$associations['companies'][$companyId] = $account->getId();
$associations['account_id'] = $account->getId();
}
}
private function processContactAssociations(array $associationIds, array &$associations): void
{
if (empty($associationIds['contacts'])) {
return;
}
foreach ($associationIds['contacts'] as $contactId) {
$contact = $this->findOrSyncContact($contactId);
if ($contact instanceof Contact) {
$associations['contacts'][$contactId] = $contact->getId();
}
}
}
private function findOrSyncAccount(string $companyId): ?Account
{
$account = $this->crmEntityRepository->findAccountByExternalId($this->config, $companyId);
if (! $account instanceof Account) {
$account = $this->syncAccount($companyId);
}
return $account;
}
private function findOrSyncContact(string $contactId): ?Contact
{
$contact = $this->crmEntityRepository->findContactByExternalId($this->config, $contactId);
if (! $contact instanceof Contact) {
$contact = $this->syncContact($contactId);
}
return $contact;
}
private function convertSingleDealAssociations($opportunityAssociations = null): array
{
$associationData = [];
if ($opportunityAssociations === null) {
return $associationData;
}
// Handle array input (from extractAssociationIds)
if (is_array($opportunityAssociations)) {
return $opportunityAssociations;
}
// Handle CollectionResponseAssociatedId object
if ($opportunityAssociations instanceof CollectionResponseAssociatedId) {
foreach ($opportunityAssociations->getResults() as $association) {
$associationData[] = $association->getId();
}
}
return $associationData;
}
private function importOrUpdateOpportunity($crmData, ?bool $exists = null): ?Opportunity
{
if (empty($crmData['properties'])) {
return null;
}
$crmId = (string) $crmData['id'];
$properties = $crmData['properties'];
$associations = $crmData['associations'] ?? [];
$opportunityExists = $exists ?? (bool) $this->crmEntityRepository->findOpportunityByExternalId(
$this->config,
$crmId
);
if ($opportunityExists) {
return $this->updateOpportunity($crmId, $properties, $associations);
} else {
return $this->createOpportunity($crmId, $properties, $associations);
}
}
/**
* Create new opportunity
*/
private function createOpportunity(string $crmId, array $properties, array $associations): ?Opportunity
{
$accountId = $this->resolveAccountId($associations);
if (! $accountId) {
return null;
}
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
if (! $businessProcess) {
return null;
}
$stage = $this->resolveStage($businessProcess, $properties['dealstage'] ?? null);
if (! $stage) {
return null;
}
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->importOpportunityContacts($opportunity, $associations['contacts']);
if ($opportunity->wasRecentlyCreated) {
MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());
}
return $opportunity;
}
/**
* Update existing opportunity
*/
private function updateOpportunity(string $crmId, array $properties, array $associations): Opportunity
{
$accountId = $this->resolveAccountId($associations);
$businessProcess = $this->resolveBusinessProcess($properties['pipeline'] ?? null);
$stage = $businessProcess ? $this->resolveStage($businessProcess, $properties['dealstage'] ?? null) : null;
$data = $this->buildOpportunityData($properties, $accountId, $businessProcess, $stage);
$attributes = [
'crm_configuration_id' => $this->config->getId(),
'crm_provider_id' => $crmId,
];
$values = array_merge($attributes, $data);
$opportunity = $this->crmEntityRepository->upsertOpportunity($attributes, $values);
$this->importExternalFieldData($properties, $opportunity->getId());
$this->updateOpportunityAssociations($opportunity, $associations);
return $opportunity;
}
private function resolveAccountId(array $associations): ?int
{
if (! empty($associations['accountId'])) {
return $associations['accountId'];
}
if (empty($associations)) {
return null;
}
// we can't resolve multiple account ids (currently SDK returns one company)
foreach ($associations['companies'] as $accountId) {
return $accountId;
}
return null;
}
private function buildOpportunityData(
array $properties,
?int $accountId,
?BusinessProcess $businessProcess,
?Stage $stage
): array {
$ownerId = null;
$profile = null;
if (! empty($properties['hubspot_owner_id'])) {
$ownerId = $properties['hubspot_owner_id'];
$profile = $this->crmEntityRepository->findProfileByExternalId($this->config, (string) $ownerId);
}
$name = 'Unknown';
if (isset($properties['dealname'])) {
$name = mb_strimwidth($properties['dealname'], 0, 128);
}
$amount = $this->resolveAmount($properties);
$currency = $properties['deal_currency_code'] ?? null;
$closeDate = null;
if (! empty($properties['closedate'])) {
$closeDate = Carbon::parse($properties['closedate'])->format('Y-m-d');
}
$remotelyCreatedAt = null;
if (! empty($properties['createdate']) && strtotime($properties['createdate'])) {
$date = $this->parseCleanDatetime($properties['createdate']);
$remotelyCreatedAt = $date?->format('Y-m-d H:i:s');
}
$closedStages = $this->getClosedDealStages();
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$data = [
'team_id' => $this->team->getId(),
'user_id' => $profile ? $profile->user_id : null,
'owner_id' => $ownerId,
'name' => $name,
'value' => ! empty($amount) ? $amount : null,
'currency_code' => CurrencyFormatter::formatCode($currency),
'close_date' => $closeDate,
'is_closed' => $isWon || $isLost,
'is_won' => $isWon,
'remotely_created_at' => $remotelyCreatedAt,
'probability' => $this->resolveDealProbability($properties['hs_deal_stage_probability']),
'forecast_category' => $this->resolveForecastCategory($properties['hs_manual_forecast_category']),
];
if ($accountId) {
$data['account_id'] = $accountId;
}
if ($stage) {
$data['stage_id'] = $stage->id;
}
if ($businessProcess) {
$recordType = $this->crmEntityRepository->getBusinessProcessRecordType($businessProcess);
if ($recordType) {
$data['record_type_id'] = $recordType->id;
}
}
return $data;
}
private function resolveBusinessProcess(?string $pipelineId): ?BusinessProcess
{
if ($pipelineId === null) {
return null;
}
if (isset($this->cachedBusinessProcesses[$pipelineId])) {
return $this->cachedBusinessProcesses[$pipelineId];
}
$businessProcess = $this->getBusinessProcess($pipelineId);
if (! $businessProcess instanceof BusinessProcess) {
$this->importStages();
$businessProcess = $this->getBusinessProcess($pipelineId);
}
if (! $businessProcess instanceof BusinessProcess) {
$this->logger->info(
'[HubSpot] Deal is not attached to a pipeline',
[
'pipeline' => $pipelineId]
);
}
$this->cachedBusinessProcesses[$pipelineId] = $businessProcess;
return $businessProcess;
}
private function getBusinessProcess(string $pipelineId): ?BusinessProcess
{
return $this->crmEntityRepository->findBusinessProcessesByExternalId($this->config, $pipelineId);
}
private function resolveStage(BusinessProcess $businessProcess, ?string $stageId): ?Stage
{
if (empty($stageId)) {
return null;
}
$cacheKey = $businessProcess->getId() . ':' . $stageId;
if (isset($this->cachedStages[$cacheKey])) {
return $this->cachedStages[$cacheKey];
}
$stage = $this->crmEntityRepository->getPipelineStageByConditions(
$businessProcess,
[
'crm_provider_id' => $stageId,
'type' => Stage::TYPE_OPPORTUNITY,
]
);
if ($stage === null) {
$this->importStages(null, $stageId);
}
if ($stage === null) {
$this->logger->info('[HubSpot] Stage does not exist => ' . $stageId);
}
$this->cachedStages[$cacheKey] = $stage;
return $stage;
}
private function resolveAmount(array $properties): ?string
{
$amount = null;
if (! empty($properties['amount'])) {
$amount = str_replace(',', '', $properties['amount']);
}
if ($this->config->hasDefaultCurrencyFieldSet()) {
$valueFieldName = $this->config->getDefaultCurrencyField()->getCrmProviderId();
$amount = $properties[$valueFieldName] ?? $amount;
}
return $amount;
}
private function parseCleanDatetime(string $datetime): ?Carbon
{
// Treat pre-1980 values as invalid
$minValidDate = Carbon::parse('1980-01-01 00:00:00');
try {
$date = Carbon::parse($datetime);
if ($minValidDate->gt($date)) {
return null;
}
return $date;
} catch (Exception) {
return null; // On parse error, treat as null
}
}
private function resolveDealProbability(?string $stageProbability): int
{
if ($stageProbability === null) {
return 0;
}
$probability = (float) $stageProbability;
return $probability > 1 ? 0 : (int) ($probability * 100);
}
private function resolveForecastCategory(?string $forecastCategory): string
{
if (! $forecastCategory) {
return Forecast::FORECAST_CATEGORY_UNCATEGORIZED;
}
$forecastCategory = str_replace('_', ' ', $forecastCategory);
return ucwords(strtolower($forecastCategory));
}
private function importExternalFieldData(array $properties, int $opportunityId): void
{
$crmFields = $this->getOpportunitySyncableFields();
$this->importOpportunityCrmFieldData($properties, $crmFields, $opportunityId);
}
private function importOpportunityContacts(Opportunity $opportunity, array $associations): void
{
// Handle empty or missing contact associations
if (empty($associations)) {
// Remove all existing contact associations if none provided
$this->removeAllOpportunityContacts($opportunity);
return;
}
// Use differential sync approach for better performance and accuracy
$this->syncOpportunityContactsDifferential($opportunity, $associations);
}
/**
* Sync opportunity contacts using differential approach
* This compares current vs new associations and only makes necessary changes
*/
private function syncOpportunityContactsDifferential(Opportunity $opportunity, array $contactAssociations): void
{
$currentContactCrmIds = $this->getCurrentContactCrmIds($opportunity);
$contactAssociationIds = array_keys($contactAssociations);
$contactsToAdd = array_diff($contactAssociationIds, $currentContactCrmIds);
$contactsToRemove = array_diff($currentContactCrmIds, $contactAssociationIds);
if (empty($contactsToAdd) && empty($contactsToRemove)) {
return;
}
$this->logContactAssociationChanges($opportunity, $currentContactCrmIds, $contactAssociations, $contactsToAdd, $contactsToRemove);
$this->removeContactAssociations($opportunity, $contactsToRemove);
$this->addContactAssociations($opportunity, $contactsToAdd, $contactAssociations);
}
private function getCurrentContactCrmIds(Opportunity $opportunity): array
{
return $opportunity->contacts()
->pluck('contacts.crm_provider_id')
->toArray();
}
private function logContactAssociationChanges(
Opportunity $opportunity,
array $currentContactCrmIds,
array $contactAssociations,
array $contactsToAdd,
array $contactsToRemove
): void {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association changes', [
'opportunity_id' => $opportunity->getId(),
'current_contacts' => $currentContactCrmIds,
'new_contacts' => $contactAssociations,
'contacts_to_add' => $contactsToAdd,
'contacts_to_remove' => $contactsToRemove,
]);
}
private function removeContactAssociations(Opportunity $opportunity, array $contactsToRemove): void
{
if (empty($contactsToRemove)) {
return;
}
$contactsToDetach = $opportunity->contacts()
->whereIn('contacts.crm_provider_id', $contactsToRemove)
->pluck('contacts.id')
->toArray();
if (! empty($contactsToDetach)) {
$opportunity->contacts()->detach($contactsToDetach);
$this->logger->info('[' . $this->getDisplayName() . '] Removed contact associations', [
'opportunity_id' => $opportunity->getId(),
'removed_contact_crm_ids' => $contactsToRemove,
'removed_contact_count' => count($contactsToDetach),
]);
}
}
private function addContactAssociations(Opportunity $opportunity, array $contactsToAdd, array $contactAssociations): void
{
if (empty($contactsToAdd)) {
return;
}
$contactsAdded = [];
foreach ($contactsToAdd as $crmId) {
$id = $contactAssociations[$crmId];
if ($this->attachSingleContact($opportunity, (string) $crmId, $id)) {
$contactsAdded[] = $crmId;
}
}
$this->logAddedContacts($opportunity, $contactsAdded);
}
private function attachSingleContact(Opportunity $opportunity, string $crmId, int $id): bool
{
try {
$contact = $this->crmEntityRepository->findContactByConfigurationAndId($this->config, $id);
if (! $contact) {
return false;
}
return $this->performContactAttachment($opportunity, $contact, $crmId);
} catch (\Throwable $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Failed to add contact association', [
'opportunity_id' => $opportunity->getId(),
'contact_crm_id' => $crmId,
'error' => $e->getMessage(),
]);
return false;
}
}
private function performContactAttachment(Opportunity $opportunity, Contact $contact, string $crmId): bool
{
try {
$opportunity->contacts()->attach($contact->getId(), [
'crm_provider_id' => $crmId,
]);
return true;
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
$this->logger->info('[' . $this->getDisplayName() . '] Contact association already exists', [
'contact_id' => $contact->getId(),
'contact_crm_id' => $crmId,
'opportunity_id' => $opportunity->getId(),
]);
return false;
}
throw $e;
}
}
private function logAddedContacts(Opportunity $opportunity, array $contactsAdded): void
{
if (! empty($contactsAdded)) {
$this->logger->info('[' . $this->getDisplayName() . '] Added contact associations', [
'opportunity_id' => $opportunity->getId(),
'contacts_to_add_count' => count($contactsAdded),
'added_contact_crm_ids' => $contactsAdded,
'added_contacts_count' => count($contactsAdded),
]);
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<template>
<WelcomeLayout
title="Account disconnected"
textPosition="center"
:icon="faUnlink"
:class="$style.layout"
>
<div :class="$style.container" v-if="providersLoaded">
<p>
<strong>
It looks like your {{ localProvider.displayName }} account has become
disconnected
</strong>
</p>
<p :class="$style.small">Please re-connect to continue</p>
<p v-if="isInIframe">
We'll open the {{ localProvider.displayName }} authentication in a new
tab. Please return here and refresh the page once complete
</p>
<GoogleLikeButton
v-if="localProvider.viaIntegrationApp && crmTokenLoaded"
as="a"
:key="localProvider.name"
:brand-logo="localProvider.name"
:class="$style.connectButton"
@click="integrationAppOnClick"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
<GoogleLikeButton
v-if="!localProvider.viaIntegrationApp"
as="a"
:key="localProvider.name"
:href="`/auth/redirect/${localProvider.name}`"
:target="target"
:brand-logo="localProvider.name"
:class="$style.connectButton"
>
Sign in with {{ localProvider.displayName }}
</GoogleLikeButton>
</div>
<BuildInfo />
<KioskBanner />
</WelcomeLayout>
</template>
<script>
import window from "window";
import axios from "axios";
import { faUnlink } from "@fortawesome/pro-regular-svg-icons";
import isInIframe from "@/utils/isInIframe";
import BuildInfo from "@/components/layout/BuildInfo/BuildInfo.vue";
import KioskBanner from "@/components/shared/KioskBanner/KioskBanner.vue";
import WelcomeLayout from "@/components/layout/WelcomeLayout/WelcomeLayout.vue";
import GoogleLikeButton from "@/components/shared/Buttons/GoogleLikeButton.vue";
import { showSnackbarError, normalizeError } from "@/utils/index";
import { IntegrationAppClient } from "@integration-app/sdk";
export default {
name: "ConnectPage",
components: {
BuildInfo,
KioskBanner,
WelcomeLayout,
GoogleLikeButton,
},
data() {
return {
...window.connectData,
crmToken: null,
faUnlink,
isInIframe,
providers: [],
providersLoaded: false,
crmTokenLoaded: false,
};
},
computed: {
localProvider() {
return this.providers.find((e) => e.name === this.provider);
},
target() {
return this.isInIframe ? "_blank" : null;
},
},
created() {
this.getProviders();
},
mounted() {
this.showErrors();
},
watch: {
providersLoaded() {
if (this.providersLoaded) {
this.prepareIntegrationAppConnection();
}
},
},
methods: {
showErrors() {
if (!this.error) return;
showSnackbarError(this.error, undefined, undefined, false);
},
unwrapEntityResponse({ data }) {
return data.map(({ icon, name, displayName, viaIntegrationApp }) => {
return { icon, name, displayName, viaIntegrationApp };
});
},
async getProviders() {
try {
const response = await axios.get("/api/v1/connect-providers");
this.providers = this.unwrapEntityResponse(response);
this.providersLoaded = true;
} catch {
showSnackbarError(
"An error occurred, while loading form data (connect providers).",
);
}
},
async prepareIntegrationAppConnection() {
if (this.localProvider.viaIntegrationApp) {
try {
const response = await axios.get("/api/v1/integration-app-token");
this.crmToken = response.data.token;
this.crmTokenLoaded = true;
} catch (error) {
console.log(error);
showSnackbarError(
`An error occurred while preparing the page.
Try refreshing, if the error persists get in touch with the Jiminny team.`,
);
}
}
},
async integrationAppOnClick() {
console.log('[IntegrationApp] integrationAppOnClick called');
const integrationApp = new IntegrationAppClient({
token: this.crmToken,
});
const connection = await integrationApp
.integration(this.localProvider.name)
.openNewConnection({
showPoweredBy: false,
allowMultipleConnections: false,
}).catch((err) => {
console.log('[IntegrationApp] openNewConnection rejected:', err);
return null;
});
console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));
// [IntegrationApp] openNewConnection resolved: {
// "id":"69e0b41a67d0068c2ca0b48e",
// "name":"Zoho CRM",
// "userId":"1ece66c8-feb1-4df1-b321-21607daf4623",
// "tenantId":"69e0b3faef3e7b6248189289",
// "isTest":false,
// "connected":true,
// "state":"READY",
// "errors":[],
// "integrationId":"66fe6c913202f3a165e3c14d",
// "externalAppId":"6671653e7e2d642e4e41b0fa",
// "authOptionKey":"",
// "createdAt":"2026-04-16T10:04:10.420Z",
// "updatedAt":"2026-04-16T10:04:10.575Z",
// "retryAttempts":0,
// "isDeactivated":false
// }
if (connection && connection.disconnected !== true && connection.connected !== false) {
console.log('[IntegrationApp] connection condition matched');
try {
const saveRequest = await axios.post(
"/api/v1/integration-app-connect",
);
if (saveRequest.data && saveRequest.data.success === true) {
/** If all is good refresh the page here */
window.location = "/dashboard";
return;
}
throw new Error(saveRequest.data.message);
} catch (error) {
console.log(error);
showSnackbarError(normalizeError(error));
}
}
},
},
};
</script>
<style module lang="less" src="./connect.less"></style>...
|
NULL
|
|
46971
|
990
|
0
|
2026-04-17T10:58:43.889038+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423523889_m2.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY] v© AutomatedReportsService.php© SendReportJob.php© SendReportMailJob.php= custom.logE laravel.logA SF [jiminny@localhost]C scratch_1jsonconnect.vue x||V Onboard.vue> D_tests_© ReportController.phpTokenBuilder.phpc leamsetuocontroller.onpphp api.php< Hs local liminnyalocalnost4 console [EUl© CrmEntityRepository.phpfi crm_configurations (EU]O connect.lessV connect.vue• Filesystem.php© Team.php© CreateHeldActivityEvent.php© TrackProviderInstalledEvent.phpA console [PROD]A console [STAGING]dashboardC RequestGenerateReportJob.phpOpportunitySyncTrait.php© Opportunity.php<script>O DeallnsightsT InteractsWithPivotTable.phgerrorPagesOpoorunityupdaled.onoOpoonunitystadeupaated.onomethods: {async getProviders() {export-portalc) FventService?rovider.onm© OpportunityPendingAiAnalysisAfterStageChanged.phpextension-installled© RunOpportunityAiAnalysis.php© ProcessAiAutomationAnalysisResults.php© ImportOpportunityBatch.phpinvitationonconterence( ImportBatchJobTrait.php(C) Service.phpasync prepareIntegrationAppConnection() {MlavoutcachedStagesCcWif (this.localProvider.viaIntegrationApp) {LiveCoachtry {_ Lockedtrait OpportunitySyncTrait433 X2 X19const response - awalt axtos.gect aped incegration-app-coken"):O login› C MeetingConsent1018private function resolveForecastCategory(?string $forecastCategory): string{...127uns,criloken = response.cdta, tokenrinis.crmlokenLoaded = urueO mobile2 usages=129f catch (error) {Conboard1029private function importExternalFieldData(array $properties, int $opportunityI, 130console. log(error);› _mocks_1030131showSnackbarError(•U_tests_$crmFields = $this->get0pportunitySyncableFields();=132"An error occurred while preparing the page.V MobileAppDownk$this->importOpportunityCrmFieldData($properties, $crmFields,$opportunityj133Try refreshing, if the error persists get in touch with the Liminny team.0 Onboard.lessV Onboard vueTs useProvidersSyn‹ondemandplayback• playlistsSettingsO sharedSoftphoneCoach10331034103510481049105010511052=135Lusaeesprivate function import0pportunityContacts(Opportunity $opportunity, array $as:137=138/**139* Sync opportunity contacts using differential approach=140* This compares current vs new associations and only makes necessary changes141Syglcons1 usage› _ leaminsightsprivate function syncOpportunityContactsDifferential(Opportunity $opportunity, 144> M composables> M7 directives> M7 helpers> → locales> D pluginsD routerstoreDutilsIS main.jsts types.d.ts10701071107710781079108010811082146Is types.jsviteasync integrationApp0nClick() {console.log('[IntegrationApp] integrationAppOnClick called');const integrationApp = new IntegrationAppClient({token: this.crmToken,7):const connection = await integrationAppintegration(this.localProvider.name)-openNewConnection(fshowPoweredBy: false,aLlownultipleconnections: talse,1 usageF) . catch((err) => {private function logContactAssociationChanges(console.log('[IntegrationApp]openNewConnection rejected:', err);Opportunity Sopportunity,recurn nutl.array $currentContactCrmIds,F):array $contactAssociations,array $contactsToAdd,array econcacustokemove): void {...}private function getCurrentContactCrmIds(Opportunity $opportunity): arrayf….} 147console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));=owsersiste=.env.default10841093// [IntegrationApp] openNewConnection resolved: {"1d". "oye0b41a6/dbb6oczcaub4oe","name":"Zoho CRM".services+,o,cv D Databasevdtuc console 1s 59 msun crm conticurations "s 391msv & minnvo ocanost4SF4 HS_localV A PROD4 console 1 s 806 msV A STAGING& consoleOutputID # 1695 X2 rows yTx: AutoyMy3VLf6XZVLQRQd0jUSrKV7cXnoDDB6zgwKg0ozEBvu2HnCmKsNV.ICIsImtpZCI6IjVmNWFhZGFkLTQwZDktNDLkNy04ZWI2LTAzNmNLM...• expires YI refresh_token_expires Y177642648417296136151776509176. provider Yu cooqle<null> zoom-phone<null> integration-app! state Yconnectedfull-refreshfull-refreshsnortcuts contlicts: Clone Caret Above and 1 more snortcut contlict with macos snortcuts. Modiry these snortcuts or change macos systemsettings. // Modify Shortcuts // Don't Show Again (today 12:22)loblj Support Daily • in 1h 2 mAAutomatedRenortsCommandTest100% 145Fri 17 Apr 13:58:43CascadeAutomated Report RetrDebugging OpportunitUpdate Connection Loconnect.vue tront-end/src/components/connecV1.Vnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your (IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check:1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? — vou may be runnina a stale build that doesn't include vour changesSearched.intecrationAooOnClickin tront-enc/src/cnect.vue (2)The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44• connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [IntegraLlonAdo intecracionAppuncllck called arter cllckine tne ourion, tne dev server nash t olckea ue tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).wAsk anything (284L)+ <> Code Claude Sonnet 4.6Wauth_scope Yhttps://www.googleapis.com/auth/userinfo.email openid https://www.googleapis.com/auth/calendar https:..phone:read:admin user:read:admin<null>CSV vДOB,retry_after Y00 cr2020<nul><null>20242026-W Windsurf Teams 139:35 (14 chars) V UTF-8fh 2 spaces...
|
NULL
|
2198973065545033263
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY] v© AutomatedReportsService.php© SendReportJob.php© SendReportMailJob.php= custom.logE laravel.logA SF [jiminny@localhost]C scratch_1jsonconnect.vue x||V Onboard.vue> D_tests_© ReportController.phpTokenBuilder.phpc leamsetuocontroller.onpphp api.php< Hs local liminnyalocalnost4 console [EUl© CrmEntityRepository.phpfi crm_configurations (EU]O connect.lessV connect.vue• Filesystem.php© Team.php© CreateHeldActivityEvent.php© TrackProviderInstalledEvent.phpA console [PROD]A console [STAGING]dashboardC RequestGenerateReportJob.phpOpportunitySyncTrait.php© Opportunity.php<script>O DeallnsightsT InteractsWithPivotTable.phgerrorPagesOpoorunityupdaled.onoOpoonunitystadeupaated.onomethods: {async getProviders() {export-portalc) FventService?rovider.onm© OpportunityPendingAiAnalysisAfterStageChanged.phpextension-installled© RunOpportunityAiAnalysis.php© ProcessAiAutomationAnalysisResults.php© ImportOpportunityBatch.phpinvitationonconterence( ImportBatchJobTrait.php(C) Service.phpasync prepareIntegrationAppConnection() {MlavoutcachedStagesCcWif (this.localProvider.viaIntegrationApp) {LiveCoachtry {_ Lockedtrait OpportunitySyncTrait433 X2 X19const response - awalt axtos.gect aped incegration-app-coken"):O login› C MeetingConsent1018private function resolveForecastCategory(?string $forecastCategory): string{...127uns,criloken = response.cdta, tokenrinis.crmlokenLoaded = urueO mobile2 usages=129f catch (error) {Conboard1029private function importExternalFieldData(array $properties, int $opportunityI, 130console. log(error);› _mocks_1030131showSnackbarError(•U_tests_$crmFields = $this->get0pportunitySyncableFields();=132"An error occurred while preparing the page.V MobileAppDownk$this->importOpportunityCrmFieldData($properties, $crmFields,$opportunityj133Try refreshing, if the error persists get in touch with the Liminny team.0 Onboard.lessV Onboard vueTs useProvidersSyn‹ondemandplayback• playlistsSettingsO sharedSoftphoneCoach10331034103510481049105010511052=135Lusaeesprivate function import0pportunityContacts(Opportunity $opportunity, array $as:137=138/**139* Sync opportunity contacts using differential approach=140* This compares current vs new associations and only makes necessary changes141Syglcons1 usage› _ leaminsightsprivate function syncOpportunityContactsDifferential(Opportunity $opportunity, 144> M composables> M7 directives> M7 helpers> → locales> D pluginsD routerstoreDutilsIS main.jsts types.d.ts10701071107710781079108010811082146Is types.jsviteasync integrationApp0nClick() {console.log('[IntegrationApp] integrationAppOnClick called');const integrationApp = new IntegrationAppClient({token: this.crmToken,7):const connection = await integrationAppintegration(this.localProvider.name)-openNewConnection(fshowPoweredBy: false,aLlownultipleconnections: talse,1 usageF) . catch((err) => {private function logContactAssociationChanges(console.log('[IntegrationApp]openNewConnection rejected:', err);Opportunity Sopportunity,recurn nutl.array $currentContactCrmIds,F):array $contactAssociations,array $contactsToAdd,array econcacustokemove): void {...}private function getCurrentContactCrmIds(Opportunity $opportunity): arrayf….} 147console.log('[IntegrationApp] openNewConnection resolved:', JSON.stringify(connection));=owsersiste=.env.default10841093// [IntegrationApp] openNewConnection resolved: {"1d". "oye0b41a6/dbb6oczcaub4oe","name":"Zoho CRM".services+,o,cv D Databasevdtuc console 1s 59 msun crm conticurations "s 391msv & minnvo ocanost4SF4 HS_localV A PROD4 console 1 s 806 msV A STAGING& consoleOutputID # 1695 X2 rows yTx: AutoyMy3VLf6XZVLQRQd0jUSrKV7cXnoDDB6zgwKg0ozEBvu2HnCmKsNV.ICIsImtpZCI6IjVmNWFhZGFkLTQwZDktNDLkNy04ZWI2LTAzNmNLM...• expires YI refresh_token_expires Y177642648417296136151776509176. provider Yu cooqle<null> zoom-phone<null> integration-app! state Yconnectedfull-refreshfull-refreshsnortcuts contlicts: Clone Caret Above and 1 more snortcut contlict with macos snortcuts. Modiry these snortcuts or change macos systemsettings. // Modify Shortcuts // Don't Show Again (today 12:22)loblj Support Daily • in 1h 2 mAAutomatedRenortsCommandTest100% 145Fri 17 Apr 13:58:43CascadeAutomated Report RetrDebugging OpportunitUpdate Connection Loconnect.vue tront-end/src/components/connecV1.Vnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your (IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check:1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? — vou may be runnina a stale build that doesn't include vour changesSearched.intecrationAooOnClickin tront-enc/src/cnect.vue (2)The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44• connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [IntegraLlonAdo intecracionAppuncllck called arter cllckine tne ourion, tne dev server nash t olckea ue tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).wAsk anything (284L)+ <> Code Claude Sonnet 4.6Wauth_scope Yhttps://www.googleapis.com/auth/userinfo.email openid https://www.googleapis.com/auth/calendar https:..phone:read:admin user:read:admin<null>CSV vДOB,retry_after Y00 cr2020<nul><null>20242026-W Windsurf Teams 139:35 (14 chars) V UTF-8fh 2 spaces...
|
46970
|
|
46972
|
989
|
0
|
2026-04-17T10:58:43.881105+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423523881_m1.jpg...
|
PhpStorm
|
faVsco.js – ~/jiminny/app/front-end/src/components faVsco.js – ~/jiminny/app/front-end/src/components/connect/connect.vue...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-383446358230247080
|
-7627610635727811642
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelp>0.(dla]-zsh• ₴8526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kB120.67kB128.71kB129.28 kB133.44kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43kB689.63kB825.23 kB1,402.70 kBSupport Daily - in 1h 2 mAPP (-zsh)DOCKER• ₴1DEV (docker)• ₴2APP (-zsh)X3-zshX4./public/vue-assets/assets/ondemand-DkNR1-pf.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-BWvQyROv.js:./public/vue-assets/assets/AskAnything-BNRpAA8H.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-Cd83royC.js./public/vue-assets/assets/deal-view-BHTz2Ksy.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-5wFR1ij2.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-D1qld9L0.js./public/vue-assets/assets/StatusBadge-CbqQ5gnA.js./public/vue-assets/assets/kiosk-DSF1ebGq.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-LnukdLUQ.js../public/vue-assets/assets/ListView-Bcd0qibH.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-C4k4MPim.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-BQx81U9A.js:./public/vue-assets/assets/OrgSettingsLayout-BQgZ11_y.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D_95E_To.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js../public/vue-assets/assets/team-insights-NuK2ryxe.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-C1SbBwo3.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CAouXZsY.js:./public/vue-assets/assets/logged-in-layout-ehXyHVjH.js* Review screenp...gzip:9.39kBgz1p:10.18kBgzip:9.58kB9z1p:10.62kB9z1p:14.97kBgzip:12.70kBgzip:12.69kBgzip:14.34kBgz1p:16.46kBgzip:15.07kBgz1p:13.28kBgzip:20.09kBgzip:18.88kB9z1p:21.85kB921p:22.96kBgzip:22.65kBgzip:27.46kBgzip:gzip:28.17kB33.78kBgzip:38.71 kBgz1p:34.16 kBgzip:40.05kBgzip:36.72 kBgzip:43.03 kB9z1p:52.24kBgz1p:56.15kBgzip:67.85kBgzip:61.85kBgz1p:64.16kBgzip:60.31KB9z1p:77.22kBgz1p:103.86kBgzip:84.90kB9z1p:97.05kBgzip: 202.81kBgzip:72.54kBgzip: 438.07kB• [EMAIL]:73.94kBmap:93.18kBmap:78.74kBmap:115.18kBmap:173.20 kBmap:138.34kBmap:150.73kBmap:150.62kBmap:294.48kBmap:153.25kBmap:65..85kBmap:239..59kBmap:219.27kBmap:201.38kBmap:244.72kBmap:300.68kBmap:3,452.35kBmap:292.79kBmap:308.10 kBmap:500.60 kBmap:258.56kBmap:410.48kBmap:266.15kBmap:516.67kBmap:831..82kBmap:623.43kBmap:836.88kBmap:684.87kBmap: 1,108.20kBmap:475.61kBmap:959.96kBmap:1,245.28kBmap:849.05kBmap:792.41kBmap:3,016.64kBmap:436.62kBmap: 6,283.55kB[plugin builtin:vite-reporter](!) Some chunks are larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
46969
|
|
47061
|
NULL
|
0
|
2026-04-17T11:03:21.057156+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423801057_m1.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelplab|Support Daily - in 57 m100% <47APP (-zsh)X4-zshDOCKER-881DEV (docker)O ₴2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-DkNR1-pf.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-BWvQyROv.js:./public/vue-assets/assets/AskAnything-BNRpAA8H.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-Cd83royC.js./public/vue-assets/assets/deal-view-BHTz2Ksy.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-5wFR1ij2.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-D1qld9L0.js./public/vue-assets/assets/StatusBadge-CbqQ5gnA.js./public/vue-assets/assets/kiosk-DSF1ebGq.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-LnukdLUQ.js../public/vue-assets/assets/ListView-Bcd0qibH.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-C4k4MPim.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-BQx81U9A.js:./public/vue-assets/assets/OrgSettingsLayout-BQgZ11_y.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D_95E_To.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js../public/vue-assets/assets/team-insights-NuK2ryxe.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-C1SbBwo3.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CAouXZsY.js:./public/vue-assets/assets/logged-in-layout-ehXyHVjH.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kB120.67kB128.71kB129.28 kB133.44kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43kB689.63kB825.23 kB1,402.70 kB[plugin builtin:vite-reporter](!) Some chunks are larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
-3177134468110149169
|
NULL
|
click
|
ocr
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelplab|Support Daily - in 57 m100% <47APP (-zsh)X4-zshDOCKER-881DEV (docker)O ₴2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-DkNR1-pf.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-BWvQyROv.js:./public/vue-assets/assets/AskAnything-BNRpAA8H.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-Cd83royC.js./public/vue-assets/assets/deal-view-BHTz2Ksy.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-5wFR1ij2.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-D1qld9L0.js./public/vue-assets/assets/StatusBadge-CbqQ5gnA.js./public/vue-assets/assets/kiosk-DSF1ebGq.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-LnukdLUQ.js../public/vue-assets/assets/ListView-Bcd0qibH.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-C4k4MPim.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-BQx81U9A.js:./public/vue-assets/assets/OrgSettingsLayout-BQgZ11_y.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D_95E_To.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js../public/vue-assets/assets/team-insights-NuK2ryxe.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-C1SbBwo3.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CAouXZsY.js:./public/vue-assets/assets/logged-in-layout-ehXyHVjH.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kB120.67kB128.71kB129.28 kB133.44kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43kB689.63kB825.23 kB1,402.70 kB[plugin builtin:vite-reporter](!) Some chunks are larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
|
47062
|
NULL
|
0
|
2026-04-17T11:03:21.026440+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423801026_m2.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileFditViewNavigateCodelaravelRefactonToo PhpStormFileFditViewNavigateCodelaravelRefactonToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY] v>W testsU connect.lessV connect.vuedashboardW DeallnsightsD errorPages_ export-portalextension-installledinvitationvonconterenceMlavoutD LiveCoach› Locked>D login>D MeetingConsent_ mobilel onboardl•__mocks_•U_tests_V MobileAppDownk1 Onboard.lessV Onboard vueTs useProvidersSyncondemandplaybackD playlistsW Settingsshared_ SoftphoneCoach• Usegicons_leaminsightscomposaoes> M7 directives> M7 helpers> → locales>_ pluginsrouter• storeD utilsus main.jsTs types.a.tsJstypes.jsI Vite= owsersistE env defaultC AutomatedReportsService.phpC) SendReportJob.phpC SendReportMailJob.php= custom.loc= aravel.logc SF liminny@localhostU scratch_1,jsonconnect.vueV Onboard.vue XC ReportController.phpTokenBuilder.phpc leamsetuocontroller.onppnp apl.ono< Hs local liminnyalocalnost4 console [EUlC CrmEntityRepository.pho(iii) crm configurations [EU]© Filesystem.php© Team.phpC RequestGenerateReportJob.php© CreateHeldActivityEvent.php© TrackProviderInstalledEvent.phpOpportunitySyncTrait.phpC Opportunity.phpT InteractsWithPivotTable.phgOpoorunityupdaled.onoOpoonunitystadeupaated.onoc) FventService?rovider.onm(c OnnortunitvPendindAiAnalvsisatterstadechanded.omC RunOpportunityAiAnalysis.phpC ProcessAlAutomationAnalysiskesults.onv© ImportOpportunityBatch.php¿ console IPRODIIc console [STAGING]<script>379setup() (const crmconnectintegrationApp = async function O 1477const integrationApp = new IntegrationAppClientetoken: crmToken.value.V1V9 AVTImportBatchJobTrait.php(C) Service.phpcachedStagesCcW1018trait upportunitysynctraitA33 V2 V19private function resolverorecastcategory(?string pforecastCategory): stringi.• 5062 usagesprivate tunecion importexternalele uabatatarray epropertzes, zht sopportunity ru*509const connection = awalt integrationApp. integration(crmbetalls.name)ovenvevronnectlonssnowPoweredby: talse,aLLowulrloleconnectons. tauseF):1050§507510console.Log(' [IntegrationAn&openNewConnection resolved:', JSON.stringify(connection)):$crmFields = $this->getOpportunitySyncableFields:Sthis->inportOpportunitvCrmFieldDataSproperties. ScrmFields.lSOOOONUILE103310341035104810491056105111054Lusaees/**private function importupportunatycontacts (Opportunaty sopportunity, array sas:516* Sync opportunity contacts using differentzal approach* Inis compares current vs new associacions and only makes necessary changes=513=5171518519if (!connection | connection.disconnected === true | connection.connected === false) ishowsnackbarErrord"A connection with your cRM could not be established".);returnhtry 1consr saverequest = valt axos.oos col vnccoraron-doo-connecr1076107110771078107910861081108410841093SZ11 usage522private tunccion syncupporcunttyconcactsultterenclat upporcunicy gopportunity.523524525private function getCurrentContactCrmIds(Opportunity Sopportunity): array.....526— 52752815291550if (saveRequest.data &x saveRequest.data.success === true) ‹** If all is good refresh the page here *return location.reloadhlusageprivate function logcontactAssoclationchangesOpportunity sopportunityarray scurrenccontacuermias,array scontaccassoclatlons.array scontacusioAdd,array +concacustokemove0: void {...}chrow new trror(saverequest.daca.message):f catch (error) {console.looterror).snowonackoarerrorunoriauzerrror error.054=533534548=5495501const preparelntegrationAppConnection = async function O k...rAif (crmRequired) 1Prepare the crm token only if the CRM is requiredLocal CnandesShelfLogconsoeLog xChanges 10 files=.env.local app(© ActivityController.php app/Http/Controllers/APlV connect.vue front-end/src/components/connect(C JiminnyDebugCommand.php app/Console/Commandsphp logging.php contigV Onboard.vue front-end/src/components/onboard© Playbackservice.php app/ServicesC ReportController.php app/Http/Controllers/Webhook(C) SyncTolntercom.ohp app/.Jobs/Teampnp weo.ono rouresUnversioned Files 8 filesslae-by-side viewerDo not ignore -Mionlleht worasmboocterc_tront-enc/src/comoonents/onooard/onboard.vueshowrowereoby: tauseaLLoyuuroleconneccons. tause.7);if (iconnection connection.disconnected === truelshowSnackbarError"A connection with your CRM could not be established".):return;• Support Daily • in 57 mA100% 145Fri 17 Apr 14:03:20AutomatedRenortsCommandTestCascadeAutomated Report RetDebugging OpportunitUpdate Connection Lcconnect.vue tront-end/src/components/connecnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your [IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check1. Is the button actually calling integrationApponclick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? - you may be running a stale build that doesn't include your changesSearched.intecrationAoo@nClickin tront-enc/src/ccents/connect/connect.vue (2)The binding looks correct. The most likely issue is a stale build — your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see (Integratlonado incecrac1onApouncllck called arter cllckine tne outton, tne dev server nasn't olckea up tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).WAsk anything (884L)+ <> Code Claude Sonnet 4.62 differencescurrent versionallowMultipleConnections: false,console.log'lIntegrationAppl openNewConnection resolved:', JSON.stringify(connection)):if (iconnection connection.disconnected === true connection.connected === false) <showSnackbarError("A connection with your CRM could not be established",return;W Windsurf Teams 510:95 V UTF-8f 2 spaces...
|
NULL
|
6534610863620137170
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileFditViewNavigateCodelaravelRefactonToo PhpStormFileFditViewNavigateCodelaravelRefactonToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY] v>W testsU connect.lessV connect.vuedashboardW DeallnsightsD errorPages_ export-portalextension-installledinvitationvonconterenceMlavoutD LiveCoach› Locked>D login>D MeetingConsent_ mobilel onboardl•__mocks_•U_tests_V MobileAppDownk1 Onboard.lessV Onboard vueTs useProvidersSyncondemandplaybackD playlistsW Settingsshared_ SoftphoneCoach• Usegicons_leaminsightscomposaoes> M7 directives> M7 helpers> → locales>_ pluginsrouter• storeD utilsus main.jsTs types.a.tsJstypes.jsI Vite= owsersistE env defaultC AutomatedReportsService.phpC) SendReportJob.phpC SendReportMailJob.php= custom.loc= aravel.logc SF liminny@localhostU scratch_1,jsonconnect.vueV Onboard.vue XC ReportController.phpTokenBuilder.phpc leamsetuocontroller.onppnp apl.ono< Hs local liminnyalocalnost4 console [EUlC CrmEntityRepository.pho(iii) crm configurations [EU]© Filesystem.php© Team.phpC RequestGenerateReportJob.php© CreateHeldActivityEvent.php© TrackProviderInstalledEvent.phpOpportunitySyncTrait.phpC Opportunity.phpT InteractsWithPivotTable.phgOpoorunityupdaled.onoOpoonunitystadeupaated.onoc) FventService?rovider.onm(c OnnortunitvPendindAiAnalvsisatterstadechanded.omC RunOpportunityAiAnalysis.phpC ProcessAlAutomationAnalysiskesults.onv© ImportOpportunityBatch.php¿ console IPRODIIc console [STAGING]<script>379setup() (const crmconnectintegrationApp = async function O 1477const integrationApp = new IntegrationAppClientetoken: crmToken.value.V1V9 AVTImportBatchJobTrait.php(C) Service.phpcachedStagesCcW1018trait upportunitysynctraitA33 V2 V19private function resolverorecastcategory(?string pforecastCategory): stringi.• 5062 usagesprivate tunecion importexternalele uabatatarray epropertzes, zht sopportunity ru*509const connection = awalt integrationApp. integration(crmbetalls.name)ovenvevronnectlonssnowPoweredby: talse,aLLowulrloleconnectons. tauseF):1050§507510console.Log(' [IntegrationAn&openNewConnection resolved:', JSON.stringify(connection)):$crmFields = $this->getOpportunitySyncableFields:Sthis->inportOpportunitvCrmFieldDataSproperties. ScrmFields.lSOOOONUILE103310341035104810491056105111054Lusaees/**private function importupportunatycontacts (Opportunaty sopportunity, array sas:516* Sync opportunity contacts using differentzal approach* Inis compares current vs new associacions and only makes necessary changes=513=5171518519if (!connection | connection.disconnected === true | connection.connected === false) ishowsnackbarErrord"A connection with your cRM could not be established".);returnhtry 1consr saverequest = valt axos.oos col vnccoraron-doo-connecr1076107110771078107910861081108410841093SZ11 usage522private tunccion syncupporcunttyconcactsultterenclat upporcunicy gopportunity.523524525private function getCurrentContactCrmIds(Opportunity Sopportunity): array.....526— 52752815291550if (saveRequest.data &x saveRequest.data.success === true) ‹** If all is good refresh the page here *return location.reloadhlusageprivate function logcontactAssoclationchangesOpportunity sopportunityarray scurrenccontacuermias,array scontaccassoclatlons.array scontacusioAdd,array +concacustokemove0: void {...}chrow new trror(saverequest.daca.message):f catch (error) {console.looterror).snowonackoarerrorunoriauzerrror error.054=533534548=5495501const preparelntegrationAppConnection = async function O k...rAif (crmRequired) 1Prepare the crm token only if the CRM is requiredLocal CnandesShelfLogconsoeLog xChanges 10 files=.env.local app(© ActivityController.php app/Http/Controllers/APlV connect.vue front-end/src/components/connect(C JiminnyDebugCommand.php app/Console/Commandsphp logging.php contigV Onboard.vue front-end/src/components/onboard© Playbackservice.php app/ServicesC ReportController.php app/Http/Controllers/Webhook(C) SyncTolntercom.ohp app/.Jobs/Teampnp weo.ono rouresUnversioned Files 8 filesslae-by-side viewerDo not ignore -Mionlleht worasmboocterc_tront-enc/src/comoonents/onooard/onboard.vueshowrowereoby: tauseaLLoyuuroleconneccons. tause.7);if (iconnection connection.disconnected === truelshowSnackbarError"A connection with your CRM could not be established".):return;• Support Daily • in 57 mA100% 145Fri 17 Apr 14:03:20AutomatedRenortsCommandTestCascadeAutomated Report RetDebugging OpportunitUpdate Connection Lcconnect.vue tront-end/src/components/connecnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your [IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check1. Is the button actually calling integrationApponclick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? - you may be running a stale build that doesn't include your changesSearched.intecrationAoo@nClickin tront-enc/src/ccents/connect/connect.vue (2)The binding looks correct. The most likely issue is a stale build — your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see (Integratlonado incecrac1onApouncllck called arter cllckine tne outton, tne dev server nasn't olckea up tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).WAsk anything (884L)+ <> Code Claude Sonnet 4.62 differencescurrent versionallowMultipleConnections: false,console.log'lIntegrationAppl openNewConnection resolved:', JSON.stringify(connection)):if (iconnection connection.disconnected === true connection.connected === false) <showSnackbarError("A connection with your CRM could not be established",return;W Windsurf Teams 510:95 V UTF-8f 2 spaces...
|
NULL
|
|
47063
|
991
|
0
|
2026-04-17T11:03:33.569911+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423813569_m1.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelplab|Support Daily - in 57 m100% <47APP (-zsh)X4-zshDOCKER• ₴1DEV (docker)O ₴2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-DkNR1-pf.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-BWvQyROv.js:./public/vue-assets/assets/AskAnything-BNRpAA8H.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-Cd83royC.js./public/vue-assets/assets/deal-view-BHTz2Ksy.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-5wFR1ij2.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-D1qld9L0.js./public/vue-assets/assets/StatusBadge-CbqQ5gnA.js./public/vue-assets/assets/kiosk-DSF1ebGq.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-LnukdLUQ.js../public/vue-assets/assets/ListView-Bcd0qibH.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-C4k4MPim.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-BQx81U9A.js:./public/vue-assets/assets/OrgSettingsLayout-BQgZ11_y.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D_95E_To.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js../public/vue-assets/assets/team-insights-NuK2ryxe.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-C1SbBwo3.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CAouXZsY.js:./public/vue-assets/assets/logged-in-layout-ehXyHVjH.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kB120.67kB128.71kB129.28 kB133.44kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43kB689.63kB825.23 kB1,402.70 kB[plugin builtin:vite-reporter](!) Some chunks are larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
7689408882707025502
|
NULL
|
click
|
ocr
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelplab|Support Daily - in 57 m100% <47APP (-zsh)X4-zshDOCKER• ₴1DEV (docker)O ₴2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-DkNR1-pf.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-BWvQyROv.js:./public/vue-assets/assets/AskAnything-BNRpAA8H.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-Cd83royC.js./public/vue-assets/assets/deal-view-BHTz2Ksy.js:./public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-5wFR1ij2.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-D1qld9L0.js./public/vue-assets/assets/StatusBadge-CbqQ5gnA.js./public/vue-assets/assets/kiosk-DSF1ebGq.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-LnukdLUQ.js../public/vue-assets/assets/ListView-Bcd0qibH.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-C4k4MPim.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMdODr.js../public/vue-assets/assets/sentry-BQx81U9A.js:./public/vue-assets/assets/OrgSettingsLayout-BQgZ11_y.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-D_95E_To.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js../public/vue-assets/assets/team-insights-NuK2ryxe.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-C1SbBwo3.js../public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CAouXZsY.js:./public/vue-assets/assets/logged-in-layout-ehXyHVjH.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.11kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kB120.67kB128.71kB129.28 kB133.44kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43kB689.63kB825.23 kB1,402.70 kB[plugin builtin:vite-reporter](!) Some chunks are larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
47061
|
|
47064
|
992
|
0
|
2026-04-17T11:03:33.551085+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776423813551_m2.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpf Support Daily • in 57 mA100% 145Fri 17 Apr 14:03:33FV faVsco.jsT° JY-20692-fix-integration-app-[API_KEY] AutomatedReportsCommandTestvProject v© AutomatedReportsService.php© SendReportJob.php© SendReportMailJob.php= custom.log= laravel.logA SF [jiminny@localhost]C scratch_1.jsonV connect.vueV Onboard.vue xCascade> D_tests_© ReportController.phpTokenBuilder.phpc leamsetuocontroller.onpphp api.php< Hs local liminnyalocalnost4 console [EUl© CrmEntityRepository.phpfi crm_configurations (EU]Automated Report RetrDebugging OpportunitUpdate Connection LoO connect.lessV connect.vue• Filesystem.php© Team.php© CreateHeldActivityEvent.php© TrackProviderInstalledEvent.phpA console [PROD]A console [STAGING]connect.vue tront-end/src/components/connecdashboardC RequestGenerateReportJob.phpOpportunitySyncTrait.php© Opportunity.php<script>M | X1x10 1 vnothing is therewDeallnsightsOpoorunityupdaled.onoOpoonunitystadeupaated.ono379setup() (T InteractsWithPivotTable.phgerrorPages"cant see log'sD export-portalc) FventService?rovider.onn© OpportunityPendingAiAnalysisAfterStageChanged.phpconst crmconnectintegrationApp = async function O 1extension-installled477const integrationApp = new IntegrationAppClient({© RunOpportunityAiAnalysis.php© ProcessAiAutomationAnalysisResults.php© ImportOpportunityBatch.phptoken: crmToken.value,invitationvonconterence( ImportBatchJobTrait.php(C) Service.php7):MlavoutcachedStagesThe console is full of CSP warnings and errors but none of your [IntegrationApp] logs. This means intedCcWLiveCoachconst connection = await integrationApprat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.› Lockedtrait OpportunitySyncTraitA33 X2 X19. integration(crmDetails.name)Check:. openNewConnection({>D login1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to a1018private function resolveForecastCategory(?string $forecastCategory): stringf. 506different method or the component re-rendered>C MeetingConsentO mobile2 usagesE507showPoweredBy: false,aLLowuLrloleconnectlons. tause.2. Is the frontend bundle rebuilt? — you may be running a stale build that doesn't include your changesF):Conboard1029private function importExternalFieldbata(array $properties, int Sopportunity[u,509› _mocks_1030Searched.intecrationAoo@nClickintront-enc/src/coents/connect/connect.vue (2)510console.log('[IntegrationApp] onBoard ppenNewConnection resolved:', JSON.stringify(connection•U_tests_$crmFields = $this->get0pportunitySyncableFields();The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aV MobileAppDownk$this->importOpportunityCrmFieldData($properties, $crmFields,SOOOONUILE0 Onboard.less1033if (Iconnection || connection.disconnected === true || connection.connected === false)fffquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:V Onboard vueshowSnackbarError(1034Reao connectvue :158-|44Ts useProvidersSyncLusaees"A connection with your CRM could not be established",• connect.vueondemand);1035D playbackprivate function importopportunityContacts(Opportunity Sopportunity, arnay $as'516return;• playlists1048Now after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [Integr=517atlonado incecraclonAppuncllck called arter cllckine tne ourton, tne cev server nasn't olckea up tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).518Settings1049/**1050* Sync opportunity contacts using differential approachO shared519try {SoftphoneCoach1051* This compares current vs new associations and only makes necessary changesconst saveRequest = await axios.post("/api/v1/integration-app-connect");1052521Svgicons1 usageif (saveRequest.data && saveRequest.data.success === true) {_leaminsightsonvare runcron suncuooorunr contacrsumerencar uooorun "o0oorcunlcy.523/** If all is good refresh the page here */composaoes1070> M7 directives524return location.reload();> M7 helpers5251071private function getCurrentContactCrmIds(Opportunity $opportunity): arrayf…..}> → locales5261077> D plugins-527throw new Error(saveRequest.data.message);1 usageD router528f catch (error) {store1078private function logContactAssociationChanges(529console.log(error);Dutils1079Opportunity Sopportunity,Is main.js1080array $currentContactCrmIds,1550snowonackoarerrorunoria uzerrror errorarray $contactAssociations,ts types.d.tsarray $contactsToAdd,Is types.jsarray +concacustokemove533534const prepareIntegrationAppConnection = async function () {...};I Vite): void {...}Ask anything (284L)548if (crmRequired) {= owsersist1093E env.default=549// Prepare the crm token only if the CRM is required+ ‹› Code7550Claude Sonnet 4.6Local CnandesShelfLogconsoeLog xChanges 10 files, updating...slae-by-side viewerDo not ignore -Mionlleht wordso merence= .env.local app85bb8fefc front-end/src/components/onboard/Onboard.vuecurrent versionActivityController.php app/Http/Controllers/APIaLlownultipleconnections. talse,V connect.vue front-end/src/components/connect7);allowMultipLeConnections: false,7);© JiminnyDebugCommand.php app/Console/Commandsphp logging.php configif (Iconnection || connection.disconnected === true) {V Onboard.vue front-end/src/components/onboardshowSnackbarError(console.1og('[IntegrationApp] onBoard openNewConnection resolved:', JSON.stringify(connection));© PlaybackService.php app/Services"A connection with your CRM could not be established",if (Iconnection || connection.disconnected === true || connection.connected === false) {C ReportController.php app/Http/Controllers/WebhookshowSnackbarError((C) SyncTolntercom.ohp app/.Jobs/TeamTeLurT"A connection with your CRM could not be established",pnp weo.ono rouresUnversioned Files 8 filesreturn;Saving 'faVsco.js' settingsW Windsurf Teams 510:45 V UTF-8f 2 spaces...
|
NULL
|
-6727540768092660292
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpf Support Daily • in 57 mA100% 145Fri 17 Apr 14:03:33FV faVsco.jsT° JY-20692-fix-integration-app-[API_KEY] AutomatedReportsCommandTestvProject v© AutomatedReportsService.php© SendReportJob.php© SendReportMailJob.php= custom.log= laravel.logA SF [jiminny@localhost]C scratch_1.jsonV connect.vueV Onboard.vue xCascade> D_tests_© ReportController.phpTokenBuilder.phpc leamsetuocontroller.onpphp api.php< Hs local liminnyalocalnost4 console [EUl© CrmEntityRepository.phpfi crm_configurations (EU]Automated Report RetrDebugging OpportunitUpdate Connection LoO connect.lessV connect.vue• Filesystem.php© Team.php© CreateHeldActivityEvent.php© TrackProviderInstalledEvent.phpA console [PROD]A console [STAGING]connect.vue tront-end/src/components/connecdashboardC RequestGenerateReportJob.phpOpportunitySyncTrait.php© Opportunity.php<script>M | X1x10 1 vnothing is therewDeallnsightsOpoorunityupdaled.onoOpoonunitystadeupaated.ono379setup() (T InteractsWithPivotTable.phgerrorPages"cant see log'sD export-portalc) FventService?rovider.onn© OpportunityPendingAiAnalysisAfterStageChanged.phpconst crmconnectintegrationApp = async function O 1extension-installled477const integrationApp = new IntegrationAppClient({© RunOpportunityAiAnalysis.php© ProcessAiAutomationAnalysisResults.php© ImportOpportunityBatch.phptoken: crmToken.value,invitationvonconterence( ImportBatchJobTrait.php(C) Service.php7):MlavoutcachedStagesThe console is full of CSP warnings and errors but none of your [IntegrationApp] logs. This means intedCcWLiveCoachconst connection = await integrationApprat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.› Lockedtrait OpportunitySyncTraitA33 X2 X19. integration(crmDetails.name)Check:. openNewConnection({>D login1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to a1018private function resolveForecastCategory(?string $forecastCategory): stringf. 506different method or the component re-rendered>C MeetingConsentO mobile2 usagesE507showPoweredBy: false,aLLowuLrloleconnectlons. tause.2. Is the frontend bundle rebuilt? — you may be running a stale build that doesn't include your changesF):Conboard1029private function importExternalFieldbata(array $properties, int Sopportunity[u,509› _mocks_1030Searched.intecrationAoo@nClickintront-enc/src/coents/connect/connect.vue (2)510console.log('[IntegrationApp] onBoard ppenNewConnection resolved:', JSON.stringify(connection•U_tests_$crmFields = $this->get0pportunitySyncableFields();The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aV MobileAppDownk$this->importOpportunityCrmFieldData($properties, $crmFields,SOOOONUILE0 Onboard.less1033if (Iconnection || connection.disconnected === true || connection.connected === false)fffquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:V Onboard vueshowSnackbarError(1034Reao connectvue :158-|44Ts useProvidersSyncLusaees"A connection with your CRM could not be established",• connect.vueondemand);1035D playbackprivate function importopportunityContacts(Opportunity Sopportunity, arnay $as'516return;• playlists1048Now after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [Integr=517atlonado incecraclonAppuncllck called arter cllckine tne ourton, tne cev server nasn't olckea up tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).518Settings1049/**1050* Sync opportunity contacts using differential approachO shared519try {SoftphoneCoach1051* This compares current vs new associations and only makes necessary changesconst saveRequest = await axios.post("/api/v1/integration-app-connect");1052521Svgicons1 usageif (saveRequest.data && saveRequest.data.success === true) {_leaminsightsonvare runcron suncuooorunr contacrsumerencar uooorun "o0oorcunlcy.523/** If all is good refresh the page here */composaoes1070> M7 directives524return location.reload();> M7 helpers5251071private function getCurrentContactCrmIds(Opportunity $opportunity): arrayf…..}> → locales5261077> D plugins-527throw new Error(saveRequest.data.message);1 usageD router528f catch (error) {store1078private function logContactAssociationChanges(529console.log(error);Dutils1079Opportunity Sopportunity,Is main.js1080array $currentContactCrmIds,1550snowonackoarerrorunoria uzerrror errorarray $contactAssociations,ts types.d.tsarray $contactsToAdd,Is types.jsarray +concacustokemove533534const prepareIntegrationAppConnection = async function () {...};I Vite): void {...}Ask anything (284L)548if (crmRequired) {= owsersist1093E env.default=549// Prepare the crm token only if the CRM is required+ ‹› Code7550Claude Sonnet 4.6Local CnandesShelfLogconsoeLog xChanges 10 files, updating...slae-by-side viewerDo not ignore -Mionlleht wordso merence= .env.local app85bb8fefc front-end/src/components/onboard/Onboard.vuecurrent versionActivityController.php app/Http/Controllers/APIaLlownultipleconnections. talse,V connect.vue front-end/src/components/connect7);allowMultipLeConnections: false,7);© JiminnyDebugCommand.php app/Console/Commandsphp logging.php configif (Iconnection || connection.disconnected === true) {V Onboard.vue front-end/src/components/onboardshowSnackbarError(console.1og('[IntegrationApp] onBoard openNewConnection resolved:', JSON.stringify(connection));© PlaybackService.php app/Services"A connection with your CRM could not be established",if (Iconnection || connection.disconnected === true || connection.connected === false) {C ReportController.php app/Http/Controllers/WebhookshowSnackbarError((C) SyncTolntercom.ohp app/.Jobs/TeamTeLurT"A connection with your CRM could not be established",pnp weo.ono rouresUnversioned Files 8 filesreturn;Saving 'faVsco.js' settingsW Windsurf Teams 510:45 V UTF-8f 2 spaces...
|
47062
|
|
47109
|
NULL
|
0
|
2026-04-17T11:08:41.576899+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424121576_m1.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelpla6]Support Daily - in 52 m100% <47-zshAPP (-zsh)|X4-zshDOCKER• ₴1DEV (docker)O ₴2APP (-zsh)X3./public/vue-assets/assets/ondemand-DutwAJ6x.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-CjPoT6NF.js:./public/vue-assets/assets/AskAnything-a4BpUaF5.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CtfldUq7.js:./public/vue-assets/assets/deal-view-DhouIWLw.js../public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWns-By9.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-BENebgvU.js./public/vue-assets/assets/StatusBadge-CmcY3nfX.js./public/vue-assets/assets/kiosk-1vhk4_89.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-DN-kVyxK.js../public/vue-assets/assets/ListView-POU6dSu7.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-DYH5MiIH.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMd0Dr.js../public/vue-assets/assets/sentry-c0Rhilsu.js:./public/vue-assets/assets/OrgSettingsLayout-ByQjX4wG.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-BH9MB7YC.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js./public/vue-assets/assets/team-insights-BqCZQtVc.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-XL9ZmWsU.js./public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CPycMtZF.js../public/vue-assets/assets/logged-in-layout-B_JDhk5y.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.26kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 28.48s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
2213734560777715800
|
NULL
|
click
|
ocr
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelpla6]Support Daily - in 52 m100% <47-zshAPP (-zsh)|X4-zshDOCKER• ₴1DEV (docker)O ₴2APP (-zsh)X3./public/vue-assets/assets/ondemand-DutwAJ6x.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-CjPoT6NF.js:./public/vue-assets/assets/AskAnything-a4BpUaF5.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CtfldUq7.js:./public/vue-assets/assets/deal-view-DhouIWLw.js../public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWns-By9.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-BENebgvU.js./public/vue-assets/assets/StatusBadge-CmcY3nfX.js./public/vue-assets/assets/kiosk-1vhk4_89.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-DN-kVyxK.js../public/vue-assets/assets/ListView-POU6dSu7.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-DYH5MiIH.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMd0Dr.js../public/vue-assets/assets/sentry-c0Rhilsu.js:./public/vue-assets/assets/OrgSettingsLayout-ByQjX4wG.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-BH9MB7YC.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js./public/vue-assets/assets/team-insights-BqCZQtVc.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-XL9ZmWsU.js./public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CPycMtZF.js../public/vue-assets/assets/logged-in-layout-B_JDhk5y.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.26kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 28.48s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
|
47110
|
NULL
|
0
|
2026-04-17T11:08:43.572469+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424123572_m2.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY].php-cs-fixer.dist.phpphp.phpstorm.meta.php=.phpunit.result.cacheE.prettierignoreE windsurfrulespip _lde_nelper.pnppnpce neloermoces.onepnp aruisani composer.isonO composer.lockdependency-checker.jsonO dev.jsonE ids.txt=infection.json.distM-INSALL.mdM+ INTERNAL WEBHOOK SETUPjiminny_storageM+ licenses.mdM MakefileOpackage-lock.json= phpstan.neon.dist= phpstan-baseline.neon< phpunit.xmlTa raw_sqLquery.sqlM+ README.mdsonar-project.properties= test.py<> Untitled Diagram.xmlI5 vetur.config.jsM-+ WEbnOOK HILIEKING_IMPLE› Iib External Librariesv E® Scratches and Consolesv D Database Consoles101819281030cachedStagesCcW165trait OpportunitySyncTraitA33 X2 X19 A Y 166private function resolveForecastCategory(?string $forecastCategory): stringf...1672 usages=169private function importExternalFieldData(array $properties, int $opportunityIa, 170171$crmFields = $this->getOpportunitySyncableFieldsO;=172$this->import0pportunityCrmFieldData(Sproperties, $crmFields, Sopportunityi17310331034103510481049105010511052=175176Lusaeesprivate function importOpportunityContacts(Opportunity Sopportunity, array $as:177=179/*** Sync opportunity contacts using differential approach180* This compares current vs new associations and only makes necessary changes1811821 usageprivate function syncOpportunityContactsDifferential(Opportunity $opportunity,10701 usageprivate function getcurrentContactCrmIds(Opportunity $opportunity): array{..., 187A console [EU]4 DEAL RISKS [EU]A DI [EU]dEuleUv& jiminny@localhost& console [jiminny@localr4 DI liiminnv@localhosti4 HS_local [jiminny@localA SF [jiminny@localhost]A zoho_dev [jiminny@loceY A PROD© AutomatedReportsService.phpC ReportController.php© SendReportJob.phplokenbullaer.onoc leamsetuocontroller.onp• Filesystem.php© Team.php© RequestGenerateReportJob.phpT InteractsWithPivotTable.phg© CreateHeldActivityEvent.phpOpportunitySyncTrait.phpC OpportunityUpdated.php© SendReportMailJob.phpphp api.php© TrackProviderlnstalledEvent.phpC Opportunity.phpC OpportunityStageUpdated.phpc) FventService?rovider.onm© RunOpportunityAiAnalysis.php( ImportBatchJobTrait.php© OpportunityPendingAiAnalysisAfterStageChanged.php© ProcessAiAutomationAnalysisResults.php(C) Service.php© ImportOpportunityBatch.phpД0/1107710781079108010811 usageprivate function logContactAssociationChanges(Opportunity Sopportunity,array $currentContactCrmIds,array $contactAssociations,array $contactsToAdd,array +concacustokemove): void {...}-189190191192services+,o₫|v D DatabasevdtuA console 1 s 59 msuni crm conticurations "s 391 msdjiminny@localhost4SF4 HS_localV A PROD4 console 1 s 806 msV A STAGINGA consoleOutputf # 16952 rows y+=S9TTy: Autoy1y3VLf6XLVLQRQd0jUSrKV7cXnoDDB6zgwKg0ozEBvu2HnCmKsNV…2 CIsImtpZCI6IjVmNWFhZGFkLTQwZDktND1kNy04ZWI2LTAzNmN1M...QM0AФW expires Y177642648417296136151776509176refresh_token_expires Y! provider Yu coodle<null> zoom-phone<null> integration-appShortcuts conflicts: Clone Caret Above and 1 more shortottings. // Modify Shortcuts // Don't Show Again (today 12:22)= custom.log< Hs local liminnyalocalnostA console [PROD]E laravel.logA SF [jiminny@localhost] XC scratch_1jsonA console (EU]© CrmEntityRepository.phpA console [(STAGING]V connect.vuefi crm_configurations (EU]V Onboard.vueXAutovPlaygroundSELECT * FROM automated_reports order by za desc;SELECT * FROMautomated_report_results order by id desc;select * from activity_searches where user_id = 143;select * from ask_anything_prompts;ma liminnvv09 A12 V2 V4 л VSELECT * FROM groups WHERE id = 1439;SELECT * FROM users WHERE group_id = 1439;select * from permissions; # 158select * from roles;select * from permission_role,select * from teams where id = 1;select * from groups g JOIN playbooks p 1.n<->1: on g.playbook_id = p.id where g.team_id = 1;select * from groups where id = 28;select * from playbooks where team_id = 1;select * from playbooks where id = 179;select * from playbook_categories where id = 1391;select * from users where id = 143;select * from crm_profiles where user_id = 143;select * from activities where crm_configuration_id = 39 and type = 'conference'and crm_provider_id IS NOT NULL ORDER by id desc;select * from activities where id = 422003; # 00U0400000pB6FpMACSELECT ar.ig, ar.wuig, ar.mediantxpe, ar.status, a.txReFROM automated_report_results arJOIN automated_reports a ON a.id = ar.repontaidWHERE a.txpe = 'ask_jiminnx"LIMIT 10;select * from teams where id = 3143;select * from crm_configurations where id = 500;select * from users where name = 'Integration Account'; # 1695SELECT * FROM social_accounts WHERE sociable_id = 1695;f Support Daily • in 52 mAL AutomatedReportsCommandTestv100% 145Fri 17 Apr 14:08:43CascadeAutomated Report RetrDebugging OpportunitUpdate Connection Loconnect.vue tront-end/src/components/connecnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your [IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check:1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? — you may be running a stale build that doesn't include your changesSearched.intecrationAoo@nClickintront-enc/src/coents/connect/connect.vue (2)The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44• connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [IntegraLlonAdo intecracionAppuncllck called arter cllckine tne ourion, tne dev server nash t olckea ue tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).O ll .wAsk anything (284L)+ <> Code Claude Sonnet 4.6I state Yconnectedfull-refreshfull-refresheI auth_scope Ynttps://www.googleap1s.com/auch/user1nro.ema1l open1d nuups://www.googleap1s.com/auch/calendar nuups..phone:read:admin user:read:adminSHULLeCSV vДOB,Wretry_after YID creaShULD2026-04<nul><null>2024-12026-04W Windsurf Teams 192:20 0 UTF-84 spaces...
|
NULL
|
-7584938818329207593
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorToo PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY].php-cs-fixer.dist.phpphp.phpstorm.meta.php=.phpunit.result.cacheE.prettierignoreE windsurfrulespip _lde_nelper.pnppnpce neloermoces.onepnp aruisani composer.isonO composer.lockdependency-checker.jsonO dev.jsonE ids.txt=infection.json.distM-INSALL.mdM+ INTERNAL WEBHOOK SETUPjiminny_storageM+ licenses.mdM MakefileOpackage-lock.json= phpstan.neon.dist= phpstan-baseline.neon< phpunit.xmlTa raw_sqLquery.sqlM+ README.mdsonar-project.properties= test.py<> Untitled Diagram.xmlI5 vetur.config.jsM-+ WEbnOOK HILIEKING_IMPLE› Iib External Librariesv E® Scratches and Consolesv D Database Consoles101819281030cachedStagesCcW165trait OpportunitySyncTraitA33 X2 X19 A Y 166private function resolveForecastCategory(?string $forecastCategory): stringf...1672 usages=169private function importExternalFieldData(array $properties, int $opportunityIa, 170171$crmFields = $this->getOpportunitySyncableFieldsO;=172$this->import0pportunityCrmFieldData(Sproperties, $crmFields, Sopportunityi17310331034103510481049105010511052=175176Lusaeesprivate function importOpportunityContacts(Opportunity Sopportunity, array $as:177=179/*** Sync opportunity contacts using differential approach180* This compares current vs new associations and only makes necessary changes1811821 usageprivate function syncOpportunityContactsDifferential(Opportunity $opportunity,10701 usageprivate function getcurrentContactCrmIds(Opportunity $opportunity): array{..., 187A console [EU]4 DEAL RISKS [EU]A DI [EU]dEuleUv& jiminny@localhost& console [jiminny@localr4 DI liiminnv@localhosti4 HS_local [jiminny@localA SF [jiminny@localhost]A zoho_dev [jiminny@loceY A PROD© AutomatedReportsService.phpC ReportController.php© SendReportJob.phplokenbullaer.onoc leamsetuocontroller.onp• Filesystem.php© Team.php© RequestGenerateReportJob.phpT InteractsWithPivotTable.phg© CreateHeldActivityEvent.phpOpportunitySyncTrait.phpC OpportunityUpdated.php© SendReportMailJob.phpphp api.php© TrackProviderlnstalledEvent.phpC Opportunity.phpC OpportunityStageUpdated.phpc) FventService?rovider.onm© RunOpportunityAiAnalysis.php( ImportBatchJobTrait.php© OpportunityPendingAiAnalysisAfterStageChanged.php© ProcessAiAutomationAnalysisResults.php(C) Service.php© ImportOpportunityBatch.phpД0/1107710781079108010811 usageprivate function logContactAssociationChanges(Opportunity Sopportunity,array $currentContactCrmIds,array $contactAssociations,array $contactsToAdd,array +concacustokemove): void {...}-189190191192services+,o₫|v D DatabasevdtuA console 1 s 59 msuni crm conticurations "s 391 msdjiminny@localhost4SF4 HS_localV A PROD4 console 1 s 806 msV A STAGINGA consoleOutputf # 16952 rows y+=S9TTy: Autoy1y3VLf6XLVLQRQd0jUSrKV7cXnoDDB6zgwKg0ozEBvu2HnCmKsNV…2 CIsImtpZCI6IjVmNWFhZGFkLTQwZDktND1kNy04ZWI2LTAzNmN1M...QM0AФW expires Y177642648417296136151776509176refresh_token_expires Y! provider Yu coodle<null> zoom-phone<null> integration-appShortcuts conflicts: Clone Caret Above and 1 more shortottings. // Modify Shortcuts // Don't Show Again (today 12:22)= custom.log< Hs local liminnyalocalnostA console [PROD]E laravel.logA SF [jiminny@localhost] XC scratch_1jsonA console (EU]© CrmEntityRepository.phpA console [(STAGING]V connect.vuefi crm_configurations (EU]V Onboard.vueXAutovPlaygroundSELECT * FROM automated_reports order by za desc;SELECT * FROMautomated_report_results order by id desc;select * from activity_searches where user_id = 143;select * from ask_anything_prompts;ma liminnvv09 A12 V2 V4 л VSELECT * FROM groups WHERE id = 1439;SELECT * FROM users WHERE group_id = 1439;select * from permissions; # 158select * from roles;select * from permission_role,select * from teams where id = 1;select * from groups g JOIN playbooks p 1.n<->1: on g.playbook_id = p.id where g.team_id = 1;select * from groups where id = 28;select * from playbooks where team_id = 1;select * from playbooks where id = 179;select * from playbook_categories where id = 1391;select * from users where id = 143;select * from crm_profiles where user_id = 143;select * from activities where crm_configuration_id = 39 and type = 'conference'and crm_provider_id IS NOT NULL ORDER by id desc;select * from activities where id = 422003; # 00U0400000pB6FpMACSELECT ar.ig, ar.wuig, ar.mediantxpe, ar.status, a.txReFROM automated_report_results arJOIN automated_reports a ON a.id = ar.repontaidWHERE a.txpe = 'ask_jiminnx"LIMIT 10;select * from teams where id = 3143;select * from crm_configurations where id = 500;select * from users where name = 'Integration Account'; # 1695SELECT * FROM social_accounts WHERE sociable_id = 1695;f Support Daily • in 52 mAL AutomatedReportsCommandTestv100% 145Fri 17 Apr 14:08:43CascadeAutomated Report RetrDebugging OpportunitUpdate Connection Loconnect.vue tront-end/src/components/connecnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your [IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check:1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? — you may be running a stale build that doesn't include your changesSearched.intecrationAoo@nClickintront-enc/src/coents/connect/connect.vue (2)The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44• connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [IntegraLlonAdo intecracionAppuncllck called arter cllckine tne ourion, tne dev server nash t olckea ue tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).O ll .wAsk anything (284L)+ <> Code Claude Sonnet 4.6I state Yconnectedfull-refreshfull-refresheI auth_scope Ynttps://www.googleap1s.com/auch/user1nro.ema1l open1d nuups://www.googleap1s.com/auch/calendar nuups..phone:read:admin user:read:adminSHULLeCSV vДOB,Wretry_after YID creaShULD2026-04<nul><null>2024-12026-04W Windsurf Teams 192:20 0 UTF-84 spaces...
|
47108
|
|
47111
|
993
|
0
|
2026-04-17T11:08:44.705738+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424124705_m1.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelpla6]Support Daily - in 52 m100% <47-zshAPP (-zsh)|X4-zshDOCKER• ₴1DEV (docker)O ₴2APP (-zsh)X3./public/vue-assets/assets/ondemand-DutwAJ6x.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-CjPoT6NF.js:./public/vue-assets/assets/AskAnything-a4BpUaF5.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CtfldUq7.js:./public/vue-assets/assets/deal-view-DhouIWLw.js../public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWns-By9.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-BENebgvU.js./public/vue-assets/assets/StatusBadge-CmcY3nfX.js./public/vue-assets/assets/kiosk-1vhk4_89.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-DN-kVyxK.js../public/vue-assets/assets/ListView-POU6dSu7.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-DYH5MiIH.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMd0Dr.js../public/vue-assets/assets/sentry-c0Rhilsu.js:./public/vue-assets/assets/OrgSettingsLayout-ByQjX4wG.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-BH9MB7YC.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js./public/vue-assets/assets/team-insights-BqCZQtVc.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-XL9ZmWsU.js./public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CPycMtZF.js../public/vue-assets/assets/logged-in-layout-B_JDhk5y.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.26kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 28.48s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
NULL
|
-9155995599667499213
|
NULL
|
click
|
ocr
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelpla6]Support Daily - in 52 m100% <47-zshAPP (-zsh)|X4-zshDOCKER• ₴1DEV (docker)O ₴2APP (-zsh)X3./public/vue-assets/assets/ondemand-DutwAJ6x.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-CjPoT6NF.js:./public/vue-assets/assets/AskAnything-a4BpUaF5.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CtfldUq7.js:./public/vue-assets/assets/deal-view-DhouIWLw.js../public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWns-By9.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-BENebgvU.js./public/vue-assets/assets/StatusBadge-CmcY3nfX.js./public/vue-assets/assets/kiosk-1vhk4_89.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-DN-kVyxK.js../public/vue-assets/assets/ListView-POU6dSu7.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-DYH5MiIH.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMd0Dr.js../public/vue-assets/assets/sentry-c0Rhilsu.js:./public/vue-assets/assets/OrgSettingsLayout-ByQjX4wG.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-BH9MB7YC.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js./public/vue-assets/assets/team-insights-BqCZQtVc.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-XL9ZmWsU.js./public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CPycMtZF.js../public/vue-assets/assets/logged-in-layout-B_JDhk5y.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.26kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 28.48s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
47109
|
|
47113
|
994
|
0
|
2026-04-17T11:08:46.333875+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424126333_m2.jpg...
|
PhpStorm
|
faVsco.js – SF [jiminny@localhost]
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.03046875,"top":0.017361112,"width":0.0453125,"height":0.022222223},"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20692-fix-integration-app-token-auth-response-change, menu","depth":5,"bounds":{"left":0.07578125,"top":0.017361112,"width":0.15898438,"height":0.022222223},"help_text":"Git Branch: JY-20692-fix-integration-app-token-auth-response-change","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.78515625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AutomatedReportsCommandTest","depth":6,"bounds":{"left":0.803125,"top":0.017361112,"width":0.09765625,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9007813,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AutomatedReportsCommandTest'","depth":6,"bounds":{"left":0.9140625,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9273437,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96015626,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9734375,"top":0.017361112,"width":0.01328125,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9867188,"top":0.017361112,"width":0.013281226,"height":0.022222223},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Show Replace Field","depth":4,"bounds":{"left":0.12382813,"top":0.22083333,"width":0.01015625,"height":0.016666668},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":3,"bounds":{"left":0.13867188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"cachedStages","depth":4,"bounds":{"left":0.1515625,"top":0.22013889,"width":0.0515625,"height":0.013888889},"value":"cachedStages","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":3,"bounds":{"left":0.21367188,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match Case","depth":3,"bounds":{"left":0.22539063,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":3,"bounds":{"left":0.23554687,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":3,"bounds":{"left":0.24570313,"top":0.22013889,"width":0.00859375,"height":0.015277778},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":3,"bounds":{"left":0.23320313,"top":1.0,"width":0.00859375,"height":0.0},"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6433419640701390788
|
-7772847050790327996
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20692-fix-integration- Project: faVsco.js, menu
JY-20692-fix-integration-app-[API_KEY], menu
Start Listening for PHP Debug Connections
AutomatedReportsCommandTest
Run 'AutomatedReportsCommandTest'
Debug 'AutomatedReportsCommandTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Show Replace Field
Search History
cachedStages
New Line
Match Case
Words
Regex
Replace History
PhpStormFileEditViewNavigateCodeLaravelRefactorToolsWindowHelpFV faVsco.s vT° JY-20692-fix-integration-app-[API_KEY].php-cs-fixer.dist.phpphp.phpstorm.meta.php=.phpunit.result.cacheE.prettierignoreE windsurfrulespip _lde_nelper.pnppnpce neloermoces.onepnp aruisani composer.isonO composer.lockdependency-checker.jsonO dev.jsonE ids.txt=infection.json.distM-INSALL.mdM+ INTERNAL WEBHOOK SETUPjiminny_storageM+ licenses.mdM MakefileOpackage-lock.json= phpstan.neon.dist= phpstan-baseline.neon< phpunit.xmlTa raw_sqLquery.sqlM+ README.mdsonar-project.properties= test.py<> Untitled Diagram.xmlIs vetur.config.jsM-+ WEbnOOK HILIEKING_IMPLE› Iib External Librariesv E® Scratches and Consolesv D Database Consoles101819281030cachedStagesCcW165trait OpportunitySyncTraitA33 X2 X19 A Y 166private function resolveForecastCategory(?string $forecastCategory): stringf...1672 usages=169private function importExternalFieldData(array $properties, int $opportunitylra, 170171$crmFields = $this->getOpportunitySyncableFieldsO;=172$this->import0pportunityCrmFieldData(Sproperties, $crmFields, Sopportunityi17310331034103510481049105010511052=175176Lusaeesprivate function importOpportunityContacts(Opportunity Sopportunity, array $as:177=179/*** Sync opportunity contacts using differential approach180* This compares current vs new associations and only makes necessary changes1811821 usageprivate function syncOpportunityContactsDifferential(Opportunity $opportunity,1070private function getcurrentContactCrmIds(Opportunity $opportunity): array{..., 187A console [EU]4 DEAL RISKS [EU]A DI [EU]dEuleUv& jiminny@localhost& console yiminny @localr4 DI liiminnv@localhosti4 HS_local [jiminny@localA SF [jiminny@localhost]A zoho_dev [jiminny@loceY A PROD© AutomatedReportsService.phpC ReportController.php© SendReportJob.phplokenbullaer.onoc leamsetuocontroller.ono• Filesystem.php© Team.php© RequestGenerateReportJob.phpT InteractsWithPivotTable.phg© CreateHeldActivityEvent.phpOpportunitySyncTrait.phpC OpportunityUpdated.php© SendReportMailJob.phpphp api.php© TrackProviderlnstalledEvent.phpC Opportunity.phpC OpportunityStageUpdated.phpc) FventService?rovider.onn© RunOpportunityAiAnalysis.php( ImportBatchJobTrait.php© OpportunityPendingAiAnalysisAfterStageChanged.php© ProcessAiAutomationAnalysisResults.php(C) Service.php© ImportOpportunityBatch.phpД0/110771078107910801 usageprivate function logContactAssociationChanges(Opportunity Sopportunity,array $currentContactCrmIds,array $contactAssociations,array $contactsToAdd,array +concacustokemove): void {...}100-189190191192v—193services+,o,cv D DatabasevdtuA console 1 s 59 msun crm conticurations "s 391msv & minnvo ocanost4 SF 559 msc ho localV A PRODs console Is ovo msV A STAGINGA consoleOutputiD # 16953rowsyTHS9T Tx:Auto v1y3VLf6XLVLQRQd0jUSrKV7cXnoDDB6zgwKg0ozEBvu2HnCmKsNV.2 CIsImtpZCI6IjVmNWFhZGFkLTQwZDktND1kNy04ZWI2LTAzNmNM...QM0AФW expires Y177642648417296136151776509176refresh_token_expires Y! provider Yu coodle<null> zoom-phone<null> integration-appDelele selected rows= custom.logE laravel.logA SF jiminny@localhost] XC scratch_1.json< Hs local liminnyalocalnostA console (EU]© CrmEntityRepository.phpA console [PROD]A console [STAGING]XAutovPlaygroundSELECT * FROM automated_reports order by za desc;SELECT * FROMautomated_report_results order by id desc;select * from activity_searches where user_id = 143;select * from ask_anything_prompts;V connect.vuefi crm_configurations (EU]V Onboard.vueMa liminnv v09 A12 V2 V4 A VSELECT * FROM groups WHERE id = 1439;SELECT * FROM users WHERE group_id = 1439;select * from permissions; # 158select * from roles;select * from permission_role.select * from teams where id = 1;select * from groups g JOIN playbooks p 1.n<->1: on g.playbook_id = p.id where g.team_id = 1;select * from groups where id = 28;select * from playbooks where team_id = 1;select * from playbooks where id = 179;select * from playbook_categories where id = 1391;select * from users where id = 143;select * from crm_profiles where user_id = 143;select * from activities where crm_configuration_id = 39 and type = 'conference'and crm_provider_id IS NOT NULL ORDER by id desc;select * from activities where id = 422003; # 00U0400000pB6FpMACSELECT ar.ig, ar.wuig, ar.mediantxpe, ar.status, a.txReFROM automated_report_results arJOIN automated_reports a ON a.id = ar.repontaidWHERE a.txpe = 'ask_jiminnx"LIMIT 10;select * from teams where id = 3143;select * from crm_configurations where id = 500;select * from users where name = 'Integration Account'; # 1695SELECT * FROM social_accounts WHERE sociable_id = 1695;f Support Daily • in 52 mAL AutomatedReportsCommandTestv100% 145Fri 17 Apr 14:08:46CascadeAutomated Report RetrDebugging OpportunitUpdate Connection Loconnect.vue tront-end/src/components/connecnothing is there"cant see log'sThe console is full of CSP warnings and errors but none of your [IntegrationApp] logs. This means intedrat1onApponcL1ck Is never belno called at all — the burton click isn't reachine that tunction.Check:1. Is the button actually calling integrationApp0nClick? - the click handler might be bound to adifferent method or the component re-rendered2. Is the frontend bundle rebuilt? — you may be running a stale build that doesn't include your changesSearched.intecrationAoo@nClickintront-enc/src/coents/connect/connect.vue (2)The binding looks correct. The most likely issue is a stale build - your changes aren't compiled yet. Add aquick test: put a console.log before the IntegrationAppClient instantiation that's impossible to miss:Reao connectvue :158-|44• connect.vueNow after saving, hard refresh the browser ( Cmd+Shift+R ) to bust the cache. If you still don't see [IntegraLlonAdo intecracionAppuncllck called arter cllckine tne ourion, tne dev server nash t olckea ue tnechanges or the click event isn't reaching this component (e.g. another element is intercepting it).O IllwI state Yconnectedfull-refreshconnectedAsk anything (284L)+ <> Code Claude Sonnet 4.6CSVvI auth_scope YWretry_after Ynttps://www.googleap1s.com/auch/user1nro.ema1l open1d nuups://www.googleap1s.com/auch/calendar nuups..ShULDphone:read:admin user:read:admin<nul><null>• : -ID crea2026-042024-12026-04SUM: 1776509176 3:6 W Windsurf Teams 192:20 0 UTF-84 spaces...
|
NULL
|
|
47200
|
NULL
|
0
|
2026-04-17T11:13:58.138724+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424438138_m1.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/onboard
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Sign in with Zoho CRM
Sign in with Zoho CRM
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Clear the Web Console output (⌘K, Ctrl+L)
Integr
Integr
214 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Navigated to https://app.dev.jiminny.com/dashboard
Show/hide message details.
XHR
GET
https://app.dev.jiminny.com/api/v1/integration-app-token
https://app.dev.jiminny.com/api/v1/integration-app-token
[HTTP/2
200
1450ms]
Top
Switch to multi-line editor mode (Cmd + B)
...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Update your information","depth":9,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Update your information","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GENERAL","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"TIMEZONE","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option Europe/Sofia (UTC +03:00)","depth":10,"value":"Select option Europe/Sofia (UTC +03:00)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Europe/Sofia (UTC +03:00)","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"LANGUAGES SPOKEN DURING CALLS","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEFAULT SPOKEN LANGUAGE","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option English (United Kingdom)","depth":10,"value":"Select option English (United Kingdom)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"English (United Kingdom)","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"If the language isn't detected we'll default to this one","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Add language","depth":11,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CONNECT/SYNC SETTINGS","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Connect Zoho CRM","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"zohocrm Sign in with Zoho CRM","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXStaticText","text":"Sign in with Zoho CRM","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Import Calendar Meetings","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"google Sign in with Google","depth":10,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sign in with Google","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Let's Get Started!","depth":9,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Clear the Web Console output (⌘K, Ctrl+L)","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXTextField","text":"Integr","depth":15,"value":"Integr","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Integr","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"214 hidden","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Clear filter input","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Errors","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Warnings","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Info","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Logs","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Debug","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"CSS","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"XHR","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Requests","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Console Settings","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Navigated to https://app.dev.jiminny.com/dashboard","depth":20,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"XHR","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/api/v1/integration-app-token","depth":20,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/api/v1/integration-app-token","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/2","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"1450ms]","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Top","depth":16,"help_text":"Select evaluation context","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Switch to multi-line editor mode (Cmd + B)","depth":16,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":18,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-6936402857171103518
|
-7241824426406463412
|
click
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Sign in with Zoho CRM
Sign in with Zoho CRM
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Clear the Web Console output (⌘K, Ctrl+L)
Integr
Integr
214 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Navigated to https://app.dev.jiminny.com/dashboard
Show/hide message details.
XHR
GET
https://app.dev.jiminny.com/api/v1/integration-app-token
https://app.dev.jiminny.com/api/v1/integration-app-token
[HTTP/2
200
1450ms]
Top
Switch to multi-line editor mode (Cmd + B)
...
|
47196
|
|
47201
|
NULL
|
0
|
2026-04-17T11:14:00.766529+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424440766_m2.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/onboard
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Sign in with Zoho CRM
Sign in with Zoho CRM
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Zoho CRM Zoho CRM
Zoho CRM
Linking your Zoho CRM account
Linking your Zoho CRM account
Please select one of authentication options:
Connect via Membrane
Connect via Membrane
Connect via Membrane
OAuth 2.0
OAuth 2.0
OAuth 2.0
Close Dialog
Clear the Web Console output (⌘K, Ctrl+L)
Integr
Integr
230 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Navigated to https://app.dev.jiminny.com/dashboard
Show/hide message details.
XHR
GET
https://app.dev.jiminny.com/api/v1/integration-app-token
https://app.dev.jiminny.com/api/v1/integration-app-token
[HTTP/2
200
1450ms]
Show/hide message details.
GET
https://ui.integration.app/embed/integrations/zohocrm/connect?token=[JWT_TOKEN]&showPoweredBy=false&allowMultipleConnections=
https://ui.integration.app/embed/integrations/zohocrm/connect?token=[JWT_TOKEN]&showPoweredBy=false&allowMultipleConnections=
[HTTP/2
200
226ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-DQ2tm1dS.css
https://ui.integration.app/assets/index-DQ2tm1dS.css
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-DCou__JW.js
https://ui.integration.app/assets/index-DCou__JW.js
[HTTP/3
200
0ms]
None of the “sha384” hashes in the integrity attribute match the content of the subresource at “
https://fonts.googleapis.com/css2?family=IBM+Plex+Serif&display=swap
https://fonts.googleapis.com/css2?family=IBM+Plex+Serif&display=swap
”. The computed hash is “oxpr/SPifeVqNx5O/1ow9nS0QIt60XJIKkUcSrPclwH/ruMEWK7C1JNqlqUMCV5N”.
connect
connect
Show/hide message details.
GET
https://ui.integration.app/assets/RefreshConnectionPopup-P6RvdGCd.js
https://ui.integration.app/assets/RefreshConnectionPopup-P6RvdGCd.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-DRKPh6L6.js
https://ui.integration.app/assets/index-DRKPh6L6.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/RefreshConnectionPopup-_TEQhDXU.css
https://ui.integration.app/assets/RefreshConnectionPopup-_TEQhDXU.css
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/IntegrationConnectionGuard-CgFvoH9G.js
https://ui.integration.app/assets/IntegrationConnectionGuard-CgFvoH9G.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-7Ka1N6pQ.js
https://ui.integration.app/assets/index-7Ka1N6pQ.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/Routes-CDWw4D3f.js
https://ui.integration.app/assets/Routes-CDWw4D3f.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-Dg8yQbmF.js
https://ui.integration.app/assets/index-Dg8yQbmF.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/ResetButton-B5vGAh3h.js
https://ui.integration.app/assets/ResetButton-B5vGAh3h.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/flow-instance-context-CJr_s6BC.js
https://ui.integration.app/assets/flow-instance-context-CJr_s6BC.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-BhMG5VAy.css
https://ui.integration.app/assets/index-BhMG5VAy.css
[HTTP/3
200
0ms]
Show/hide message details....
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.31666666,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.3402778,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Update your information","depth":9,"bounds":{"left":0.29335937,"top":0.3375,"width":0.15273437,"height":0.016666668},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Update your information","depth":10,"bounds":{"left":0.31796876,"top":0.33541667,"width":0.103515625,"height":0.020833334},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GENERAL","depth":10,"bounds":{"left":0.29335937,"top":0.36944443,"width":0.025,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"TIMEZONE","depth":12,"bounds":{"left":0.2984375,"top":0.39722222,"width":0.0203125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option Europe/Sofia (UTC +03:00)","depth":10,"bounds":{"left":0.2984375,"top":0.40625,"width":0.14726563,"height":0.017361112},"value":"Select option Europe/Sofia (UTC +03:00)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Europe/Sofia (UTC +03:00)","depth":12,"bounds":{"left":0.2984375,"top":0.40902779,"width":0.061328124,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"bounds":{"left":0.44023436,"top":0.3923611,"width":0.003125,"height":0.017361112},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"LANGUAGES SPOKEN DURING CALLS","depth":10,"bounds":{"left":0.29335937,"top":0.44791666,"width":0.09609375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEFAULT SPOKEN LANGUAGE","depth":12,"bounds":{"left":0.2984375,"top":0.47569445,"width":0.05546875,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option English (United Kingdom)","depth":10,"bounds":{"left":0.2984375,"top":0.48472223,"width":0.14726563,"height":0.017361112},"value":"Select option English (United Kingdom)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"English (United Kingdom)","depth":12,"bounds":{"left":0.2984375,"top":0.4875,"width":0.057421874,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"bounds":{"left":0.44023436,"top":0.47083333,"width":0.003125,"height":0.017361112},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"If the language isn't detected we'll default to this one","depth":11,"bounds":{"left":0.29335937,"top":0.5076389,"width":0.109375,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Add language","depth":11,"bounds":{"left":0.29335937,"top":0.52847224,"width":0.037890624,"height":0.013888889},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CONNECT/SYNC SETTINGS","depth":10,"bounds":{"left":0.29335937,"top":0.56458336,"width":0.06992187,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Connect Zoho CRM","depth":11,"bounds":{"left":0.29335937,"top":0.5902778,"width":0.0546875,"height":0.013888889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"zohocrm Sign in with Zoho CRM","depth":10,"bounds":{"left":0.36875,"top":0.5847222,"width":0.07734375,"height":0.025},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sign in with Zoho CRM","depth":11,"bounds":{"left":0.38632813,"top":0.59097224,"width":0.054296874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Import Calendar Meetings","depth":11,"bounds":{"left":0.29335937,"top":0.62083334,"width":0.045703124,"height":0.027777778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":12,"bounds":{"left":0.3371094,"top":0.6173611,"width":0.003125,"height":0.017361112},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"google Sign in with Google","depth":10,"bounds":{"left":0.36875,"top":0.62222224,"width":0.07734375,"height":0.025},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sign in with Google","depth":11,"bounds":{"left":0.39023438,"top":0.6284722,"width":0.046484374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Let's Get Started!","depth":9,"bounds":{"left":0.3347656,"top":0.68333334,"width":0.06992187,"height":0.025},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Zoho CRM Zoho CRM","depth":12,"bounds":{"left":0.16835937,"top":0.17777778,"width":0.20625,"height":0.016666668},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Zoho CRM","depth":13,"bounds":{"left":0.18085937,"top":0.17986111,"width":0.02578125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Linking your Zoho CRM account","depth":14,"bounds":{"left":0.18046875,"top":0.30069444,"width":0.19453125,"height":0.04236111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Linking your Zoho CRM account","depth":15,"bounds":{"left":0.18046875,"top":0.31180555,"width":0.134375,"height":0.02013889},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please select one of authentication options:","depth":15,"bounds":{"left":0.18046875,"top":0.33541667,"width":0.10625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Connect via Membrane","depth":13,"bounds":{"left":0.16679688,"top":0.35694444,"width":0.221875,"height":0.033333335},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Connect via Membrane","depth":15,"bounds":{"left":0.19453125,"top":0.36805555,"width":0.055859376,"height":0.009722223},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Connect via Membrane","depth":16,"bounds":{"left":0.19453125,"top":0.3673611,"width":0.055859376,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"OAuth 2.0","depth":13,"bounds":{"left":0.16679688,"top":0.39097223,"width":0.221875,"height":0.033333335},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"OAuth 2.0","depth":15,"bounds":{"left":0.19453125,"top":0.40208334,"width":0.023828125,"height":0.009722223},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OAuth 2.0","depth":16,"bounds":{"left":0.19453125,"top":0.40138888,"width":0.023828125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close Dialog","depth":12,"bounds":{"left":0.3816406,"top":0.17638889,"width":0.0109375,"height":0.019444445},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXButton","text":"Clear the Web Console output (⌘K, Ctrl+L)","depth":15,"bounds":{"left":0.46328124,"top":0.068055555,"width":0.01015625,"height":0.013888889},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXTextField","text":"Integr","depth":15,"bounds":{"left":0.47578126,"top":0.065972224,"width":0.32851562,"height":0.018055556},"value":"Integr","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Integr","depth":16,"bounds":{"left":0.484375,"top":0.07013889,"width":0.012109375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"230 hidden","depth":16,"bounds":{"left":0.8058594,"top":0.07013889,"width":0.0234375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Clear filter input","depth":15,"bounds":{"left":0.83085936,"top":0.06944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Errors","depth":15,"bounds":{"left":0.8417969,"top":0.068055555,"width":0.0171875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Warnings","depth":15,"bounds":{"left":0.85976565,"top":0.068055555,"width":0.023828125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Info","depth":15,"bounds":{"left":0.884375,"top":0.068055555,"width":0.0125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Logs","depth":15,"bounds":{"left":0.89765626,"top":0.068055555,"width":0.014453125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Debug","depth":15,"bounds":{"left":0.9128906,"top":0.068055555,"width":0.01796875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"CSS","depth":15,"bounds":{"left":0.9359375,"top":0.068055555,"width":0.01328125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"XHR","depth":15,"bounds":{"left":0.95,"top":0.068055555,"width":0.013671875,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Requests","depth":15,"bounds":{"left":0.9644531,"top":0.068055555,"width":0.023828125,"height":0.013888889},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Console Settings","depth":15,"bounds":{"left":0.9898437,"top":0.06527778,"width":0.01015625,"height":0.019444445},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Navigated to https://app.dev.jiminny.com/dashboard","depth":20,"bounds":{"left":0.471875,"top":0.0875,"width":0.12929687,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.10138889,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"XHR","depth":21,"bounds":{"left":0.475,"top":0.10277778,"width":0.00703125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.48476562,"top":0.10208333,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/api/v1/integration-app-token","depth":20,"bounds":{"left":0.4953125,"top":0.10208333,"width":0.4441406,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/api/v1/integration-app-token","depth":21,"bounds":{"left":0.4953125,"top":0.10208333,"width":0.14453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/2","depth":21,"bounds":{"left":0.9421875,"top":0.10208333,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.96367186,"top":0.10208333,"width":0.007421875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"1450ms]","depth":21,"bounds":{"left":0.971875,"top":0.10208333,"width":0.0234375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.11666667,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.11736111,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/embed/integrations/zohocrm/connect?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjFlY2U2NmM4LWZlYjEtNGRmMS1iMzIxLTIxNjA3ZGFmNDYyMyIsIm5hbWUiOiJEZXYgWm9obyBDUk0gY2xpZW50IiwiaXNzIjoiNjg3YTU5ZjctMjI3Ni00ODZjLTgzMDYtMTQ1MDdmZDc5N2FlIiwiZXhwIjoxNzc2NTEwODMyLCJmaWVsZHMiOnsiZW52IjoibG9jYWwiLCJ3ZWJob29rVXJsIjoiaHR0cHM6Ly9xYXRlc3Q6UWFZZU14MS02NDJuYkBsdWthc2submdyb2suaW8iLCJldmVudEFjY291bnREZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2FjYy1kZWwiLCJldmVudENvbnRhY3REZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2NudC1kZWwiLCJldmVudFByb2ZpbGVEZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL3Vzci1kZWwiLCJldmVudExlYWREZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2xkLWRlbCIsImV2ZW50RGVhbERlbGV0ZWQiOiIvd2ViaG9vay9pbnRhcHAvb3BwLWRlbCIsImV2ZW50QWNjb3VudENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvYWNjLWFkZCIsImV2ZW50QWNjb3VudFVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvYWNjLXVwZCIsImV2ZW50Q29udGFjdENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvY250LWFkZCIsImV2ZW50Q29udGFjdFVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvY250LXVwZCIsImV2ZW50UHJvZmlsZUNyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvdXNyLWFkZCIsImV2ZW50UHJvZmlsZVVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvdXNyLXVwZCIsImV2ZW50TGVhZENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvbGQtYWRkIiwiZXZlbnRMZWFkVXBkYXRlZCI6Ii93ZWJob29rL2ludGFwcC9sZC11cGQiLCJldmVudERlYWxDcmVhdGVkIjoiL3dlYmhvb2svaW50YXBwL29wcC1hZGQiLCJldmVudERlYWxVcGRhdGVkIjoiL3dlYmhvb2svaW50YXBwL29wcC11cGQifX0.cPowBZuDxoTPGjFBae4ToiaiHGn8n7ip72tabpSeGsg&showPoweredBy=false&allowMultipleConnections=","depth":20,"bounds":{"left":0.484375,"top":0.11736111,"width":0.4578125,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/embed/integrations/zohocrm/connect?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjFlY2U2NmM4LWZlYjEtNGRmMS1iMzIxLTIxNjA3ZGFmNDYyMyIsIm5hbWUiOiJEZXYgWm9obyBDUk0gY2xpZW50IiwiaXNzIjoiNjg3YTU5ZjctMjI3Ni00ODZjLTgzMDYtMTQ1MDdmZDc5N2FlIiwiZXhwIjoxNzc2NTEwODMyLCJmaWVsZHMiOnsiZW52IjoibG9jYWwiLCJ3ZWJob29rVXJsIjoiaHR0cHM6Ly9xYXRlc3Q6UWFZZU14MS02NDJuYkBsdWthc2submdyb2suaW8iLCJldmVudEFjY291bnREZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2FjYy1kZWwiLCJldmVudENvbnRhY3REZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2NudC1kZWwiLCJldmVudFByb2ZpbGVEZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL3Vzci1kZWwiLCJldmVudExlYWREZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2xkLWRlbCIsImV2ZW50RGVhbERlbGV0ZWQiOiIvd2ViaG9vay9pbnRhcHAvb3BwLWRlbCIsImV2ZW50QWNjb3VudENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvYWNjLWFkZCIsImV2ZW50QWNjb3VudFVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvYWNjLXVwZCIsImV2ZW50Q29udGFjdENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvY250LWFkZCIsImV2ZW50Q29udGFjdFVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvY250LXVwZCIsImV2ZW50UHJvZmlsZUNyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvdXNyLWFkZCIsImV2ZW50UHJvZmlsZVVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvdXNyLXVwZCIsImV2ZW50TGVhZENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvbGQtYWRkIiwiZXZlbnRMZWFkVXBkYXRlZCI6Ii93ZWJob29rL2ludGFwcC9sZC11cGQiLCJldmVudERlYWxDcmVhdGVkIjoiL3dlYmhvb2svaW50YXBwL29wcC1hZGQiLCJldmVudERlYWxVcGRhdGVkIjoiL3dlYmhvb2svaW50YXBwL29wcC11cGQifX0.cPowBZuDxoTPGjFBae4ToiaiHGn8n7ip72tabpSeGsg&showPoweredBy=false&allowMultipleConnections=","depth":21,"bounds":{"left":0.484375,"top":0.11736111,"width":0.515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/2","depth":21,"bounds":{"left":0.94453126,"top":0.11736111,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.96601564,"top":0.11736111,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"226ms]","depth":21,"bounds":{"left":0.9746094,"top":0.11736111,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.13125,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.13194445,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/index-DQ2tm1dS.css","depth":20,"bounds":{"left":0.484375,"top":0.13194445,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/index-DQ2tm1dS.css","depth":21,"bounds":{"left":0.484375,"top":0.13194445,"width":0.134375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.13194445,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.13194445,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.13194445,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.14583333,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.14652778,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/index-DCou__JW.js","depth":20,"bounds":{"left":0.484375,"top":0.14652778,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/index-DCou__JW.js","depth":21,"bounds":{"left":0.484375,"top":0.14652778,"width":0.13203125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.14652778,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.14652778,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.14652778,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"None of the “sha384” hashes in the integrity attribute match the content of the subresource at “","depth":21,"bounds":{"left":0.471875,"top":0.16111112,"width":0.24804688,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://fonts.googleapis.com/css2?family=IBM+Plex+Serif&display=swap","depth":21,"bounds":{"left":0.7199219,"top":0.16111112,"width":0.17578125,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://fonts.googleapis.com/css2?family=IBM+Plex+Serif&display=swap","depth":22,"bounds":{"left":0.7199219,"top":0.16111112,"width":0.17578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"”. The computed hash is “oxpr/SPifeVqNx5O/1ow9nS0QIt60XJIKkUcSrPclwH/ruMEWK7C1JNqlqUMCV5N”.","depth":21,"bounds":{"left":0.471875,"top":0.16111112,"width":0.5015625,"height":0.019444445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"connect","depth":20,"bounds":{"left":0.97734374,"top":0.16111112,"width":0.01796875,"height":0.009722223},"help_text":"View source in Debugger → https://ui.integration.app/embed/integrations/zohocrm/connect","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"connect","depth":22,"bounds":{"left":0.97734374,"top":0.16111112,"width":0.01796875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.18472221,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.18541667,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/RefreshConnectionPopup-P6RvdGCd.js","depth":20,"bounds":{"left":0.484375,"top":0.18541667,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/RefreshConnectionPopup-P6RvdGCd.js","depth":21,"bounds":{"left":0.484375,"top":0.18541667,"width":0.17578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.18541667,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.18541667,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.18541667,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.19930555,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.2,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/index-DRKPh6L6.js","depth":20,"bounds":{"left":0.484375,"top":0.2,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/index-DRKPh6L6.js","depth":21,"bounds":{"left":0.484375,"top":0.2,"width":0.13203125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.2,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.2,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.2,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.21388888,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.21458334,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/RefreshConnectionPopup-_TEQhDXU.css","depth":20,"bounds":{"left":0.484375,"top":0.21458334,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/RefreshConnectionPopup-_TEQhDXU.css","depth":21,"bounds":{"left":0.484375,"top":0.21458334,"width":0.17851563,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.21458334,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.21458334,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.21458334,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.22847222,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.22916667,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/IntegrationConnectionGuard-CgFvoH9G.js","depth":20,"bounds":{"left":0.484375,"top":0.22916667,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/IntegrationConnectionGuard-CgFvoH9G.js","depth":21,"bounds":{"left":0.484375,"top":0.22916667,"width":0.18632813,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.22916667,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.22916667,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.22916667,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.24305555,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.24375,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/index-7Ka1N6pQ.js","depth":20,"bounds":{"left":0.484375,"top":0.24375,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/index-7Ka1N6pQ.js","depth":21,"bounds":{"left":0.484375,"top":0.24375,"width":0.13203125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.24375,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.24375,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.24375,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.2576389,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.25833333,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/Routes-CDWw4D3f.js","depth":20,"bounds":{"left":0.484375,"top":0.25833333,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/Routes-CDWw4D3f.js","depth":21,"bounds":{"left":0.484375,"top":0.25833333,"width":0.134375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.25833333,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.25833333,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.25833333,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.27222222,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.27291667,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/index-Dg8yQbmF.js","depth":20,"bounds":{"left":0.484375,"top":0.27291667,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/index-Dg8yQbmF.js","depth":21,"bounds":{"left":0.484375,"top":0.27291667,"width":0.13203125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.27291667,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.27291667,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.27291667,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.28680557,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.2875,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/ResetButton-B5vGAh3h.js","depth":20,"bounds":{"left":0.484375,"top":0.2875,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/ResetButton-B5vGAh3h.js","depth":21,"bounds":{"left":0.484375,"top":0.2875,"width":0.14765625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.2875,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.2875,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.2875,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.3013889,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.30208334,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/flow-instance-context-CJr_s6BC.js","depth":20,"bounds":{"left":0.484375,"top":0.30208334,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/flow-instance-context-CJr_s6BC.js","depth":21,"bounds":{"left":0.484375,"top":0.30208334,"width":0.1734375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.30208334,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.30208334,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.30208334,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.3159722,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"bounds":{"left":0.47421876,"top":0.31666666,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/index-BhMG5VAy.css","depth":20,"bounds":{"left":0.484375,"top":0.31666666,"width":0.46289062,"height":0.009722223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/index-BhMG5VAy.css","depth":21,"bounds":{"left":0.484375,"top":0.31666666,"width":0.134375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"bounds":{"left":0.9496094,"top":0.31666666,"width":0.020703126,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"bounds":{"left":0.9710938,"top":0.31666666,"width":0.0078125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"bounds":{"left":0.9796875,"top":0.31666666,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"bounds":{"left":0.46367186,"top":0.33055556,"width":0.009375,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
435485411657637066
|
-308816509618605563
|
visual_change
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Sign in with Zoho CRM
Sign in with Zoho CRM
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Zoho CRM Zoho CRM
Zoho CRM
Linking your Zoho CRM account
Linking your Zoho CRM account
Please select one of authentication options:
Connect via Membrane
Connect via Membrane
Connect via Membrane
OAuth 2.0
OAuth 2.0
OAuth 2.0
Close Dialog
Clear the Web Console output (⌘K, Ctrl+L)
Integr
Integr
230 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Navigated to https://app.dev.jiminny.com/dashboard
Show/hide message details.
XHR
GET
https://app.dev.jiminny.com/api/v1/integration-app-token
https://app.dev.jiminny.com/api/v1/integration-app-token
[HTTP/2
200
1450ms]
Show/hide message details.
GET
https://ui.integration.app/embed/integrations/zohocrm/connect?token=[JWT_TOKEN]&showPoweredBy=false&allowMultipleConnections=
https://ui.integration.app/embed/integrations/zohocrm/connect?token=[JWT_TOKEN]&showPoweredBy=false&allowMultipleConnections=
[HTTP/2
200
226ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-DQ2tm1dS.css
https://ui.integration.app/assets/index-DQ2tm1dS.css
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-DCou__JW.js
https://ui.integration.app/assets/index-DCou__JW.js
[HTTP/3
200
0ms]
None of the “sha384” hashes in the integrity attribute match the content of the subresource at “
https://fonts.googleapis.com/css2?family=IBM+Plex+Serif&display=swap
https://fonts.googleapis.com/css2?family=IBM+Plex+Serif&display=swap
”. The computed hash is “oxpr/SPifeVqNx5O/1ow9nS0QIt60XJIKkUcSrPclwH/ruMEWK7C1JNqlqUMCV5N”.
connect
connect
Show/hide message details.
GET
https://ui.integration.app/assets/RefreshConnectionPopup-P6RvdGCd.js
https://ui.integration.app/assets/RefreshConnectionPopup-P6RvdGCd.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-DRKPh6L6.js
https://ui.integration.app/assets/index-DRKPh6L6.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/RefreshConnectionPopup-_TEQhDXU.css
https://ui.integration.app/assets/RefreshConnectionPopup-_TEQhDXU.css
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/IntegrationConnectionGuard-CgFvoH9G.js
https://ui.integration.app/assets/IntegrationConnectionGuard-CgFvoH9G.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-7Ka1N6pQ.js
https://ui.integration.app/assets/index-7Ka1N6pQ.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/Routes-CDWw4D3f.js
https://ui.integration.app/assets/Routes-CDWw4D3f.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-Dg8yQbmF.js
https://ui.integration.app/assets/index-Dg8yQbmF.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/ResetButton-B5vGAh3h.js
https://ui.integration.app/assets/ResetButton-B5vGAh3h.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/flow-instance-context-CJr_s6BC.js
https://ui.integration.app/assets/flow-instance-context-CJr_s6BC.js
[HTTP/3
200
0ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-BhMG5VAy.css
https://ui.integration.app/assets/index-BhMG5VAy.css
[HTTP/3
200
0ms]
Show/hide message details....
|
NULL
|
|
47202
|
995
|
0
|
2026-04-17T11:14:02.393199+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424442393_m1.jpg...
|
Firefox
|
Jiminny — Work
|
1
|
app.dev.jiminny.com/onboard
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Sign in with Zoho CRM
Sign in with Zoho CRM
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Zoho CRM Zoho CRM
Zoho CRM
Linking your Zoho CRM account
Linking your Zoho CRM account
Please select one of authentication options:
Connect via Membrane
Connect via Membrane
Connect via Membrane
OAuth 2.0
OAuth 2.0
OAuth 2.0
Close Dialog
Clear the Web Console output (⌘K, Ctrl+L)
Integr
Integr
230 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Navigated to https://app.dev.jiminny.com/dashboard
Show/hide message details.
XHR
GET
https://app.dev.jiminny.com/api/v1/integration-app-token
https://app.dev.jiminny.com/api/v1/integration-app-token
[HTTP/2
200
1450ms]
Show/hide message details.
GET
https://ui.integration.app/embed/integrations/zohocrm/connect?token=[JWT_TOKEN]&showPoweredBy=false&allowMultipleConnections=
https://ui.integration.app/embed/integrations/zohocrm/connect?token=[JWT_TOKEN]&showPoweredBy=false&allowMultipleConnections=
[HTTP/2
200
226ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-DQ2tm1dS.css
https://ui.integration.app/assets/index-DQ2tm1dS.css
[HTTP/3
200
0ms]
Show/hide message details.
GET...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Update your information","depth":9,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Update your information","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GENERAL","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"TIMEZONE","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option Europe/Sofia (UTC +03:00)","depth":10,"value":"Select option Europe/Sofia (UTC +03:00)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Europe/Sofia (UTC +03:00)","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"LANGUAGES SPOKEN DURING CALLS","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEFAULT SPOKEN LANGUAGE","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Select option English (United Kingdom)","depth":10,"value":"Select option English (United Kingdom)","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Select option","depth":11,"help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"English (United Kingdom)","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"If the language isn't detected we'll default to this one","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Add language","depth":11,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CONNECT/SYNC SETTINGS","depth":10,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Connect Zoho CRM","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"zohocrm Sign in with Zoho CRM","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sign in with Zoho CRM","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Import Calendar Meetings","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"*","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"google Sign in with Google","depth":10,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sign in with Google","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Let's Get Started!","depth":9,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Zoho CRM Zoho CRM","depth":12,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Zoho CRM","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Linking your Zoho CRM account","depth":14,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Linking your Zoho CRM account","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please select one of authentication options:","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Connect via Membrane","depth":13,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Connect via Membrane","depth":15,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Connect via Membrane","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"OAuth 2.0","depth":13,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OAuth 2.0","depth":15,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OAuth 2.0","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close Dialog","depth":12,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Clear the Web Console output (⌘K, Ctrl+L)","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXTextField","text":"Integr","depth":15,"value":"Integr","role_description":"search text field","subrole":"AXSearchField","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Integr","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"230 hidden","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Clear filter input","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Errors","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Warnings","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Info","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Logs","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Debug","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"CSS","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"XHR","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Requests","depth":15,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Console Settings","depth":15,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Navigated to https://app.dev.jiminny.com/dashboard","depth":20,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"XHR","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://app.dev.jiminny.com/api/v1/integration-app-token","depth":20,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://app.dev.jiminny.com/api/v1/integration-app-token","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/2","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"1450ms]","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/embed/integrations/zohocrm/connect?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjFlY2U2NmM4LWZlYjEtNGRmMS1iMzIxLTIxNjA3ZGFmNDYyMyIsIm5hbWUiOiJEZXYgWm9obyBDUk0gY2xpZW50IiwiaXNzIjoiNjg3YTU5ZjctMjI3Ni00ODZjLTgzMDYtMTQ1MDdmZDc5N2FlIiwiZXhwIjoxNzc2NTEwODMyLCJmaWVsZHMiOnsiZW52IjoibG9jYWwiLCJ3ZWJob29rVXJsIjoiaHR0cHM6Ly9xYXRlc3Q6UWFZZU14MS02NDJuYkBsdWthc2submdyb2suaW8iLCJldmVudEFjY291bnREZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2FjYy1kZWwiLCJldmVudENvbnRhY3REZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2NudC1kZWwiLCJldmVudFByb2ZpbGVEZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL3Vzci1kZWwiLCJldmVudExlYWREZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2xkLWRlbCIsImV2ZW50RGVhbERlbGV0ZWQiOiIvd2ViaG9vay9pbnRhcHAvb3BwLWRlbCIsImV2ZW50QWNjb3VudENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvYWNjLWFkZCIsImV2ZW50QWNjb3VudFVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvYWNjLXVwZCIsImV2ZW50Q29udGFjdENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvY250LWFkZCIsImV2ZW50Q29udGFjdFVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvY250LXVwZCIsImV2ZW50UHJvZmlsZUNyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvdXNyLWFkZCIsImV2ZW50UHJvZmlsZVVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvdXNyLXVwZCIsImV2ZW50TGVhZENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvbGQtYWRkIiwiZXZlbnRMZWFkVXBkYXRlZCI6Ii93ZWJob29rL2ludGFwcC9sZC11cGQiLCJldmVudERlYWxDcmVhdGVkIjoiL3dlYmhvb2svaW50YXBwL29wcC1hZGQiLCJldmVudERlYWxVcGRhdGVkIjoiL3dlYmhvb2svaW50YXBwL29wcC11cGQifX0.cPowBZuDxoTPGjFBae4ToiaiHGn8n7ip72tabpSeGsg&showPoweredBy=false&allowMultipleConnections=","depth":20,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/embed/integrations/zohocrm/connect?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjFlY2U2NmM4LWZlYjEtNGRmMS1iMzIxLTIxNjA3ZGFmNDYyMyIsIm5hbWUiOiJEZXYgWm9obyBDUk0gY2xpZW50IiwiaXNzIjoiNjg3YTU5ZjctMjI3Ni00ODZjLTgzMDYtMTQ1MDdmZDc5N2FlIiwiZXhwIjoxNzc2NTEwODMyLCJmaWVsZHMiOnsiZW52IjoibG9jYWwiLCJ3ZWJob29rVXJsIjoiaHR0cHM6Ly9xYXRlc3Q6UWFZZU14MS02NDJuYkBsdWthc2submdyb2suaW8iLCJldmVudEFjY291bnREZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2FjYy1kZWwiLCJldmVudENvbnRhY3REZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2NudC1kZWwiLCJldmVudFByb2ZpbGVEZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL3Vzci1kZWwiLCJldmVudExlYWREZWxldGVkIjoiL3dlYmhvb2svaW50YXBwL2xkLWRlbCIsImV2ZW50RGVhbERlbGV0ZWQiOiIvd2ViaG9vay9pbnRhcHAvb3BwLWRlbCIsImV2ZW50QWNjb3VudENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvYWNjLWFkZCIsImV2ZW50QWNjb3VudFVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvYWNjLXVwZCIsImV2ZW50Q29udGFjdENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvY250LWFkZCIsImV2ZW50Q29udGFjdFVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvY250LXVwZCIsImV2ZW50UHJvZmlsZUNyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvdXNyLWFkZCIsImV2ZW50UHJvZmlsZVVwZGF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvdXNyLXVwZCIsImV2ZW50TGVhZENyZWF0ZWQiOiIvd2ViaG9vay9pbnRhcHAvbGQtYWRkIiwiZXZlbnRMZWFkVXBkYXRlZCI6Ii93ZWJob29rL2ludGFwcC9sZC11cGQiLCJldmVudERlYWxDcmVhdGVkIjoiL3dlYmhvb2svaW50YXBwL29wcC1hZGQiLCJldmVudERlYWxVcGRhdGVkIjoiL3dlYmhvb2svaW50YXBwL29wcC11cGQifX0.cPowBZuDxoTPGjFBae4ToiaiHGn8n7ip72tabpSeGsg&showPoweredBy=false&allowMultipleConnections=","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/2","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"226ms]","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"https://ui.integration.app/assets/index-DQ2tm1dS.css","depth":20,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"https://ui.integration.app/assets/index-DQ2tm1dS.css","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"[HTTP/3","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"200","depth":22,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"0ms]","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show/hide message details.","depth":17,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"GET","depth":21,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
1488781543758621854
|
-324295401047094684
|
click
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Update your information
Update your information
GENERAL
TIMEZONE
Select option Europe/Sofia (UTC +03:00)
Select option
Europe/Sofia (UTC +03:00)
*
LANGUAGES SPOKEN DURING CALLS
DEFAULT SPOKEN LANGUAGE
Select option English (United Kingdom)
Select option
English (United Kingdom)
*
If the language isn't detected we'll default to this one
Add language
CONNECT/SYNC SETTINGS
Connect Zoho CRM
zohocrm Sign in with Zoho CRM
Sign in with Zoho CRM
Import Calendar Meetings
*
google Sign in with Google
Sign in with Google
Let's Get Started!
Zoho CRM Zoho CRM
Zoho CRM
Linking your Zoho CRM account
Linking your Zoho CRM account
Please select one of authentication options:
Connect via Membrane
Connect via Membrane
Connect via Membrane
OAuth 2.0
OAuth 2.0
OAuth 2.0
Close Dialog
Clear the Web Console output (⌘K, Ctrl+L)
Integr
Integr
230 hidden
Clear filter input
Errors
Warnings
Info
Logs
Debug
CSS
XHR
Requests
Console Settings
Navigated to https://app.dev.jiminny.com/dashboard
Show/hide message details.
XHR
GET
https://app.dev.jiminny.com/api/v1/integration-app-token
https://app.dev.jiminny.com/api/v1/integration-app-token
[HTTP/2
200
1450ms]
Show/hide message details.
GET
https://ui.integration.app/embed/integrations/zohocrm/connect?token=[JWT_TOKEN]&showPoweredBy=false&allowMultipleConnections=
https://ui.integration.app/embed/integrations/zohocrm/connect?token=[JWT_TOKEN]&showPoweredBy=false&allowMultipleConnections=
[HTTP/2
200
226ms]
Show/hide message details.
GET
https://ui.integration.app/assets/index-DQ2tm1dS.css
https://ui.integration.app/assets/index-DQ2tm1dS.css
[HTTP/3
200
0ms]
Show/hide message details.
GET...
|
NULL
|
|
47203
|
996
|
0
|
2026-04-17T11:14:02.393205+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424442393_m2.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Firefox FileEdit•••D+→ cView History Bookmarks P Firefox FileEdit•••D+→ cView History Bookmarks Profiles Tools Window Help• -° app.dev.jiminny.com/onboardDevelopers | HubSpotM'inbox (1,576) - lukas.kovalik@jiminM° 120216 is your HubSpot Log in CocFa CloudWatch | eu-west-1New Tabz Configure SSH access to multiple. fix-cache-for-business-processes4 [JY-20692] Issue with reconnectirg Jiminny+ New TabZ Zoho CRMLinking your Zoho CRM accountPlease select one of authentication options:° Connect via Membranei OAuth 20nationImport CalendarMeetingsin with Zoho CRMG Sign in with GoogleLet's Get Started!> 0j Support Daily • in 46 mA100% C4Fri 17 Apr 14:14:02Inspector• ConsoleD DebuggerN Network{) Style EditorA Performance: Memory& Storagei Accessibilityy Integr88 Application230 hidden XErrors Warnings InfoLogs Debug©23CSS XHRRequests© Navagated to https://app.dev.J1manny.com/dashboardXHR GET https://app.dev.iiminny.com/api/v1/integration=app-tokenGET https://ui.integration.app/embed/integrations/zohocrm/connect?token=ey]0eXAi0iJKV1QiLCJhbGci0iJIUzI1NiJ9.eyJpZCI61jFLY2U2NmM4LWZLYjEtNGRmMS1iMzIxLTIxNjA3ZGFmNDYyMyIsIm5hbWUi0i].. [HTTP/2 200 226ms]GEThttps://ui.integration.app/assets/index-D02tm1dS.cssbel nucos.u1, incedracion.app assecs/1ndex-bcou JW.SIHTTP/2200 1450ms]THITIP/3 200 Oms[HTTP/3 (200)© Noneof theattribute match the content of the subresource at "https://fonts.googleapis.com/css22family=IBM+Plex+Serif&display=swap". The computed hash is "oxpr/ connectSPifeVqNx50/10w9nS0Q[t60XJIKkUcSrPclwH/гuMEWK7C1JNqlqUMCV5N".• GET https://ui.integration.app/assets/RefreshConnectionPopup-P6RvdGCd.is• GET https://ui.integration.app/assets/index-DRKPh6L6.isGET https://ui.integration.app/assets/RefreshConnectionPopup- TEQhDXU.cssbcl ntcos.ul.1ncecracion.app/assecs/1ncecrac1onconnecclonguard-corvongb.rg• GET https://ui.integration.app/assets/index-7Ka1N6pQ.is• GET https://ui. integration.app/assets/Routes-CDWw4D3f.isbel ntcos..ur.ancecracton.apg/asseuslndex-uoowbnr.sGET https://ui.integration.app/assets/ResetButton-B5vGAh3h.isGElhttps:u1.1ntegration.app/assets/tlow-1nstance-context-cJr_sbbC.1sbel ntcos.ur.ancecraclon.aog/asseuslndex-bhiobvay.ossGET https://ui.integration.app/assets/Routes-DHLymKVa.cssGEl https:ap1.qetmembrane.com/1nteqrationszohocrmorllons ntcos:ap1.cermembrane.com 1nceorations zonochiGET https://static.integration.app/connectors/zoho-crm/loqo.pngGEThttps://static.integration.app/connectors/zoho=crm/log0.pngleihttos:/statlc.intedration.app/tzles/080de462-9a/0-462-0108-a02ctcdc4a45.0ng|Mllr3 200[HTTP/3 200 0mslІНTTP/3_200][HTTP/3 200[НTTP/3 200)IНTTP/3 200GШHS4001[HTTP/3 200 0mslHITP/S 269IНTTP/3.200[HTTP/3 200 0mslHITPS 200MIUr2204Mlur2 200 omsІНTTP/1.1 200 OK 0mslJHITIPYS 1269Top + E...
|
NULL
|
6215848050658725459
|
NULL
|
click
|
ocr
|
NULL
|
Firefox FileEdit•••D+→ cView History Bookmarks P Firefox FileEdit•••D+→ cView History Bookmarks Profiles Tools Window Help• -° app.dev.jiminny.com/onboardDevelopers | HubSpotM'inbox (1,576) - lukas.kovalik@jiminM° 120216 is your HubSpot Log in CocFa CloudWatch | eu-west-1New Tabz Configure SSH access to multiple. fix-cache-for-business-processes4 [JY-20692] Issue with reconnectirg Jiminny+ New TabZ Zoho CRMLinking your Zoho CRM accountPlease select one of authentication options:° Connect via Membranei OAuth 20nationImport CalendarMeetingsin with Zoho CRMG Sign in with GoogleLet's Get Started!> 0j Support Daily • in 46 mA100% C4Fri 17 Apr 14:14:02Inspector• ConsoleD DebuggerN Network{) Style EditorA Performance: Memory& Storagei Accessibilityy Integr88 Application230 hidden XErrors Warnings InfoLogs Debug©23CSS XHRRequests© Navagated to https://app.dev.J1manny.com/dashboardXHR GET https://app.dev.iiminny.com/api/v1/integration=app-tokenGET https://ui.integration.app/embed/integrations/zohocrm/connect?token=ey]0eXAi0iJKV1QiLCJhbGci0iJIUzI1NiJ9.eyJpZCI61jFLY2U2NmM4LWZLYjEtNGRmMS1iMzIxLTIxNjA3ZGFmNDYyMyIsIm5hbWUi0i].. [HTTP/2 200 226ms]GEThttps://ui.integration.app/assets/index-D02tm1dS.cssbel nucos.u1, incedracion.app assecs/1ndex-bcou JW.SIHTTP/2200 1450ms]THITIP/3 200 Oms[HTTP/3 (200)© Noneof theattribute match the content of the subresource at "https://fonts.googleapis.com/css22family=IBM+Plex+Serif&display=swap". The computed hash is "oxpr/ connectSPifeVqNx50/10w9nS0Q[t60XJIKkUcSrPclwH/гuMEWK7C1JNqlqUMCV5N".• GET https://ui.integration.app/assets/RefreshConnectionPopup-P6RvdGCd.is• GET https://ui.integration.app/assets/index-DRKPh6L6.isGET https://ui.integration.app/assets/RefreshConnectionPopup- TEQhDXU.cssbcl ntcos.ul.1ncecracion.app/assecs/1ncecrac1onconnecclonguard-corvongb.rg• GET https://ui.integration.app/assets/index-7Ka1N6pQ.is• GET https://ui. integration.app/assets/Routes-CDWw4D3f.isbel ntcos..ur.ancecracton.apg/asseuslndex-uoowbnr.sGET https://ui.integration.app/assets/ResetButton-B5vGAh3h.isGElhttps:u1.1ntegration.app/assets/tlow-1nstance-context-cJr_sbbC.1sbel ntcos.ur.ancecraclon.aog/asseuslndex-bhiobvay.ossGET https://ui.integration.app/assets/Routes-DHLymKVa.cssGEl https:ap1.qetmembrane.com/1nteqrationszohocrmorllons ntcos:ap1.cermembrane.com 1nceorations zonochiGET https://static.integration.app/connectors/zoho-crm/loqo.pngGEThttps://static.integration.app/connectors/zoho=crm/log0.pngleihttos:/statlc.intedration.app/tzles/080de462-9a/0-462-0108-a02ctcdc4a45.0ng|Mllr3 200[HTTP/3 200 0mslІНTTP/3_200][HTTP/3 200[НTTP/3 200)IНTTP/3 200GШHS4001[HTTP/3 200 0mslHITP/S 269IНTTP/3.200[HTTP/3 200 0mslHITPS 200MIUr2204Mlur2 200 omsІНTTP/1.1 200 OK 0mslJHITIPYS 1269Top + E...
|
47201
|
|
47285
|
NULL
|
0
|
2026-04-17T11:19:05.901113+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424745901_m1.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Membrane
Membrane
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Membrane","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Element Selectors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Element Selectors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"API Errors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"API Errors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"WORKSPACE ELEMENTS","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"WORKSPACE ELEMENTS","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connections Show subpages for Connections","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connections","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connections","depth":14,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"List connections GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connections","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connection PATCH","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connection PUT","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh connection credentials POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh connection credentials","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection logs GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection logs","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection dependencies GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection dependencies","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connection GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Restore connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Restore connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Archive connection DEL","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Archive connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connectors Hide subpages for Connectors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connectors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connectors","depth":14,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Connector Types Hide subpages for Connector Types","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Types","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connector Types","depth":16,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Client Credentials","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Client Credentials","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Token","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane Token","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth1","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-1880352834673245291
|
-7454551344340616596
|
click
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Membrane
Membrane
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1...
|
47282
|
|
47288
|
NULL
|
0
|
2026-04-17T11:19:09.692253+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424749692_m2.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Firefox FileEoitViewHistory Bookmarks Profiles T Firefox FileEoitViewHistory Bookmarks Profiles Tools Window HelpDevelopers | HubSpotM'inbox (1,576) - lukas.kovalik@jiminM° 120216 is your HubSpot Log in CocFal CloudWatch | eu-west-1New Tabz Configure SSH access to multiple. fix-cache-for-business-processes4 [JY-20692] Issue with reconnectir(8) JiminnyAuth ProxyMembrahe-= docs.getmembrane.com/reference/auth-proxyMembraneM Docs<> API ReferenceJUMPTOOVERVIEWHutnenuicalionElement SelectorsAPl ErrorsWORKSPACE ELEMENISConnectionsConnectorsConnector TypesCent CredentialsMembraneconsole.getmemorane.com+ New TabC< 40 ll O SupportDaily - in 41m100% ( Fri 17 Apr 14:19:09=Q SearchLog InWORKSPACE ELEMENTS > CONNECTORS > CONNECTOR TYPESAuth Proxy•† Ask Al vAuth Proxy lets you use OAuth credentials provided by Membrane without registering your own OAuth app.You typically don't need to use this authentication type yourself, but you may find it in pre-builtconnectors.When using Auth Proxy, you will not have access to the connection credentials.Example connector definition:YAML# Connector definition: Use Membrane-provided OAuth credentials (no custom OAuth appпесасалtype: auth-proxyproxyKey: auth-proxy-key@ Updated 30 days ago< OAuth2Connector Functions →List connectorsGETOList public connectorsGet connectorCreate connectorPatch connectorDelete connectorDownload connectorUpload connectorImport connectorClone connectorGet connector versionsPublish connector versionUpdate connectorcompletelyGet a list of connector filesGet connector file by pathUpdate connector fileDelete connector fileDelete connector directoryExport connector as zip GETIfileExport connector as JSON GETDid this page help you? & Yes INo...
|
NULL
|
8253081986799999724
|
NULL
|
visual_change
|
ocr
|
NULL
|
Firefox FileEoitViewHistory Bookmarks Profiles T Firefox FileEoitViewHistory Bookmarks Profiles Tools Window HelpDevelopers | HubSpotM'inbox (1,576) - lukas.kovalik@jiminM° 120216 is your HubSpot Log in CocFal CloudWatch | eu-west-1New Tabz Configure SSH access to multiple. fix-cache-for-business-processes4 [JY-20692] Issue with reconnectir(8) JiminnyAuth ProxyMembrahe-= docs.getmembrane.com/reference/auth-proxyMembraneM Docs<> API ReferenceJUMPTOOVERVIEWHutnenuicalionElement SelectorsAPl ErrorsWORKSPACE ELEMENISConnectionsConnectorsConnector TypesCent CredentialsMembraneconsole.getmemorane.com+ New TabC< 40 ll O SupportDaily - in 41m100% ( Fri 17 Apr 14:19:09=Q SearchLog InWORKSPACE ELEMENTS > CONNECTORS > CONNECTOR TYPESAuth Proxy•† Ask Al vAuth Proxy lets you use OAuth credentials provided by Membrane without registering your own OAuth app.You typically don't need to use this authentication type yourself, but you may find it in pre-builtconnectors.When using Auth Proxy, you will not have access to the connection credentials.Example connector definition:YAML# Connector definition: Use Membrane-provided OAuth credentials (no custom OAuth appпесасалtype: auth-proxyproxyKey: auth-proxy-key@ Updated 30 days ago< OAuth2Connector Functions →List connectorsGETOList public connectorsGet connectorCreate connectorPatch connectorDelete connectorDownload connectorUpload connectorImport connectorClone connectorGet connector versionsPublish connector versionUpdate connectorcompletelyGet a list of connector filesGet connector file by pathUpdate connector fileDelete connector fileDelete connector directoryExport connector as zip GETIfileExport connector as JSON GETDid this page help you? & Yes INo...
|
47287
|
|
47289
|
997
|
0
|
2026-04-17T11:19:36.144876+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424776144_m1.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Membrane
console.getmembrane.com
Workers | Datadog Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Membrane
Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Membrane","depth":4,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"console.getmembrane.com","depth":4,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Membrane","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-4984054004463189050
|
-2765952288667682228
|
idle
|
accessibility
|
NULL
|
Membrane
console.getmembrane.com
Workers | Datadog Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Membrane
Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication...
|
NULL
|
|
47290
|
998
|
0
|
2026-04-17T11:19:40.381943+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776424780381_m2.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Membrane
console.getmembrane.com
Workers | Datadog Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Membrane
Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET
List public connectors
GET
Get connector GET
Get connector
GET
Create connector POST
Create connector
POST
Patch connector PATCH
Patch connector
PATCH
Delete connector DEL
Delete connector
DEL
Download connector GET
Download connector
GET
Upload connector POST
Upload connector
POST
Import connector POST
Import connector
POST
Clone connector POST
Clone connector
POST
Get connector versions GET
Get connector versions
GET
Publish connector version POST
Publish connector version
POST
Update connector completely PUT
Update connector completely
PUT
Get a list of connector files GET
Get a list of connector files
GET
Get connector file by path GET...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Membrane","depth":4,"bounds":{"left":0.09804688,"top":0.37430555,"width":0.02265625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"console.getmembrane.com","depth":4,"bounds":{"left":0.09804688,"top":0.38402778,"width":0.05546875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"bounds":{"left":0.0,"top":0.33888888,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"bounds":{"left":0.015625,"top":0.34861112,"width":0.021875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.34513888,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Membrane","depth":4,"bounds":{"left":0.0,"top":0.3673611,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane","depth":5,"bounds":{"left":0.015625,"top":0.37708333,"width":0.021484375,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.37361112,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.39722222,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"bounds":{"left":0.09765625,"top":0.052083332,"width":0.048828125,"height":0.020833334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"bounds":{"left":0.1,"top":0.056944445,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"bounds":{"left":0.1015625,"top":0.048611112,"width":0.05078125,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"bounds":{"left":0.16015625,"top":0.048611112,"width":0.02421875,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"bounds":{"left":0.16132812,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"bounds":{"left":0.16992188,"top":0.05625,"width":0.01328125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"bounds":{"left":0.1921875,"top":0.048611112,"width":0.048046876,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"bounds":{"left":0.19335938,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"bounds":{"left":0.20195313,"top":0.05625,"width":0.037109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"bounds":{"left":0.90117186,"top":0.052083332,"width":0.05859375,"height":0.020833334},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"bounds":{"left":0.903125,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"bounds":{"left":0.91132814,"top":0.05625,"width":0.017578125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"bounds":{"left":0.96367186,"top":0.052083332,"width":0.024609376,"height":0.020833334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"bounds":{"left":0.96796876,"top":0.05625,"width":0.016015625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"bounds":{"left":0.099609375,"top":0.097222224,"width":0.09765625,"height":0.020833334},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"bounds":{"left":0.099609375,"top":0.14166667,"width":0.09765625,"height":0.011111111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"bounds":{"left":0.103515625,"top":0.1423611,"width":0.02578125,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"bounds":{"left":0.099609375,"top":0.16041666,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"bounds":{"left":0.103515625,"top":0.16597222,"width":0.037109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Element Selectors","depth":13,"bounds":{"left":0.099609375,"top":0.18333334,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Element Selectors","depth":15,"bounds":{"left":0.103515625,"top":0.18888889,"width":0.04609375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"API Errors","depth":13,"bounds":{"left":0.099609375,"top":0.20625,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"API Errors","depth":15,"bounds":{"left":0.103515625,"top":0.21180555,"width":0.025390625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"WORKSPACE ELEMENTS","depth":11,"bounds":{"left":0.099609375,"top":0.24930556,"width":0.09765625,"height":0.011111111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"WORKSPACE ELEMENTS","depth":12,"bounds":{"left":0.103515625,"top":0.25,"width":0.058203124,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connections Show subpages for Connections","depth":13,"bounds":{"left":0.099609375,"top":0.26805556,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connections","depth":15,"bounds":{"left":0.103515625,"top":0.2736111,"width":0.03203125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connections","depth":14,"bounds":{"left":0.1890625,"top":0.2736111,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"List connections GET","depth":15,"bounds":{"left":0.103515625,"top":0.28541666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connections","depth":17,"bounds":{"left":0.107421875,"top":0.29097223,"width":0.041796874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.2923611,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection GET","depth":15,"bounds":{"left":0.103515625,"top":0.30833334,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection","depth":17,"bounds":{"left":0.107421875,"top":0.31388888,"width":0.0390625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.31527779,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.33125,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connection","depth":17,"bounds":{"left":0.107421875,"top":0.33680555,"width":0.046875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.33819443,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connection PATCH","depth":15,"bounds":{"left":0.103515625,"top":0.35416666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connection","depth":17,"bounds":{"left":0.107421875,"top":0.35972223,"width":0.04453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"bounds":{"left":0.18085937,"top":0.3611111,"width":0.01328125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connection PUT","depth":15,"bounds":{"left":0.103515625,"top":0.37708333,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connection","depth":17,"bounds":{"left":0.107421875,"top":0.3826389,"width":0.0484375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"bounds":{"left":0.18320313,"top":0.38402778,"width":0.00859375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.4,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test connection","depth":17,"bounds":{"left":0.107421875,"top":0.40555555,"width":0.040625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.40694445,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh connection credentials POST","depth":15,"bounds":{"left":0.103515625,"top":0.42291668,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh connection credentials","depth":17,"bounds":{"left":0.107421875,"top":0.42847222,"width":0.049609374,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.4298611,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection logs GET","depth":15,"bounds":{"left":0.103515625,"top":0.45972222,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection logs","depth":17,"bounds":{"left":0.107421875,"top":0.4652778,"width":0.051171876,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.46666667,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection dependencies GET","depth":15,"bounds":{"left":0.103515625,"top":0.4826389,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection dependencies","depth":17,"bounds":{"left":0.107421875,"top":0.48819444,"width":0.0390625,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.48958334,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connection GET","depth":15,"bounds":{"left":0.103515625,"top":0.51944447,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connection","depth":17,"bounds":{"left":0.107421875,"top":0.525,"width":0.046484374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.5263889,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Restore connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.54236114,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Restore connection","depth":17,"bounds":{"left":0.107421875,"top":0.54791665,"width":0.049609374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.54930556,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Archive connection DEL","depth":15,"bounds":{"left":0.103515625,"top":0.56527776,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Archive connection","depth":17,"bounds":{"left":0.107421875,"top":0.5708333,"width":0.04921875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"bounds":{"left":0.18359375,"top":0.57222223,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connectors Hide subpages for Connectors","depth":13,"bounds":{"left":0.099609375,"top":0.29097223,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connectors","depth":15,"bounds":{"left":0.103515625,"top":0.29652777,"width":0.0296875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connectors","depth":14,"bounds":{"left":0.1890625,"top":0.29652777,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Connector Types Hide subpages for Connector Types","depth":15,"bounds":{"left":0.103515625,"top":0.31388888,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Types","depth":17,"bounds":{"left":0.107421875,"top":0.31944445,"width":0.04375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connector Types","depth":16,"bounds":{"left":0.1890625,"top":0.31944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Client Credentials","depth":17,"bounds":{"left":0.107421875,"top":0.33680555,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Client Credentials","depth":19,"bounds":{"left":0.111328125,"top":0.34236112,"width":0.0453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Token","depth":17,"bounds":{"left":0.107421875,"top":0.35972223,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane Token","depth":19,"bounds":{"left":0.111328125,"top":0.36527777,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth1","depth":17,"bounds":{"left":0.107421875,"top":0.3826389,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth1","depth":19,"bounds":{"left":0.111328125,"top":0.38819444,"width":0.018359374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth2","depth":17,"bounds":{"left":0.107421875,"top":0.40555555,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth2","depth":19,"bounds":{"left":0.111328125,"top":0.41111112,"width":0.019140625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Auth Proxy","depth":17,"bounds":{"left":0.107421875,"top":0.42847222,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Auth Proxy","depth":19,"bounds":{"left":0.111328125,"top":0.4340278,"width":0.027734375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connector Functions Show subpages for Connector Functions","depth":15,"bounds":{"left":0.103515625,"top":0.45277777,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Functions","depth":17,"bounds":{"left":0.107421875,"top":0.45833334,"width":0.053515624,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connector Functions","depth":16,"bounds":{"left":0.1890625,"top":0.45833334,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Get Credentials from Connection Parameters","depth":17,"bounds":{"left":0.107421875,"top":0.47013888,"width":0.08984375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get Credentials from Connection Parameters","depth":19,"bounds":{"left":0.111328125,"top":0.47569445,"width":0.083984375,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Make API Client","depth":17,"bounds":{"left":0.107421875,"top":0.5069444,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Make API Client","depth":19,"bounds":{"left":0.111328125,"top":0.5125,"width":0.040234376,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh Credentials","depth":17,"bounds":{"left":0.107421875,"top":0.5298611,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh Credentials","depth":19,"bounds":{"left":0.111328125,"top":0.53541666,"width":0.050390624,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test","depth":17,"bounds":{"left":0.107421875,"top":0.55277777,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test","depth":19,"bounds":{"left":0.111328125,"top":0.55833334,"width":0.0109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Disconnect","depth":17,"bounds":{"left":0.107421875,"top":0.57569444,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Disconnect","depth":19,"bounds":{"left":0.111328125,"top":0.58125,"width":0.02890625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Universal Data Models","depth":15,"bounds":{"left":0.103515625,"top":0.47569445,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Universal Data Models","depth":17,"bounds":{"left":0.107421875,"top":0.48125,"width":0.05703125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List connectors GET","depth":15,"bounds":{"left":0.103515625,"top":0.49861112,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connectors","depth":17,"bounds":{"left":0.107421875,"top":0.50416666,"width":0.039453126,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.50555557,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List public connectors GET","depth":15,"bounds":{"left":0.103515625,"top":0.52152777,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List public connectors","depth":17,"bounds":{"left":0.107421875,"top":0.52708334,"width":0.056640625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.52847224,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector GET","depth":15,"bounds":{"left":0.103515625,"top":0.54444444,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector","depth":17,"bounds":{"left":0.107421875,"top":0.55,"width":0.03671875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.55138886,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.5673611,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connector","depth":17,"bounds":{"left":0.107421875,"top":0.5729167,"width":0.04453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.57430553,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connector PATCH","depth":15,"bounds":{"left":0.103515625,"top":0.5902778,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connector","depth":17,"bounds":{"left":0.107421875,"top":0.59583336,"width":0.041796874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"bounds":{"left":0.18085937,"top":0.5972222,"width":0.01328125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Delete connector DEL","depth":15,"bounds":{"left":0.103515625,"top":0.61319447,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Delete connector","depth":17,"bounds":{"left":0.107421875,"top":0.61875,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"bounds":{"left":0.18359375,"top":0.6201389,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Download connector GET","depth":15,"bounds":{"left":0.103515625,"top":0.63611114,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Download connector","depth":17,"bounds":{"left":0.107421875,"top":0.64166665,"width":0.052734375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.64305556,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Upload connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.65902776,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Upload connector","depth":17,"bounds":{"left":0.107421875,"top":0.6645833,"width":0.045703124,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.66597223,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Import connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.68194443,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Import connector","depth":17,"bounds":{"left":0.107421875,"top":0.6875,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.6888889,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Clone connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.7048611,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Clone connector","depth":17,"bounds":{"left":0.107421875,"top":0.7104167,"width":0.0421875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.7118056,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector versions GET","depth":15,"bounds":{"left":0.103515625,"top":0.7277778,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector versions","depth":17,"bounds":{"left":0.107421875,"top":0.73333335,"width":0.059375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.7347222,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Publish connector version POST","depth":15,"bounds":{"left":0.103515625,"top":0.75069445,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Publish connector version","depth":17,"bounds":{"left":0.107421875,"top":0.75625,"width":0.06601562,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.7576389,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connector completely PUT","depth":15,"bounds":{"left":0.103515625,"top":0.7736111,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connector completely","depth":17,"bounds":{"left":0.107421875,"top":0.77916664,"width":0.04609375,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"bounds":{"left":0.18320313,"top":0.78055555,"width":0.00859375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get a list of connector files GET","depth":15,"bounds":{"left":0.103515625,"top":0.81041664,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get a list of connector files","depth":17,"bounds":{"left":0.107421875,"top":0.8159722,"width":0.06875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.8173611,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector file by path GET","depth":15,"bounds":{"left":0.103515625,"top":0.8333333,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-1098465649884243807
|
-482802647540680116
|
idle
|
accessibility
|
NULL
|
Membrane
console.getmembrane.com
Workers | Datadog Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Membrane
Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET
List public connectors
GET
Get connector GET
Get connector
GET
Create connector POST
Create connector
POST
Patch connector PATCH
Patch connector
PATCH
Delete connector DEL
Delete connector
DEL
Download connector GET
Download connector
GET
Upload connector POST
Upload connector
POST
Import connector POST
Import connector
POST
Clone connector POST
Clone connector
POST
Get connector versions GET
Get connector versions
GET
Publish connector version POST
Publish connector version
POST
Update connector completely PUT
Update connector completely
PUT
Get a list of connector files GET
Get a list of connector files
GET
Get connector file by path GET...
|
NULL
|
|
47309
|
NULL
|
0
|
2026-04-17T11:24:38.628802+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425078628_m1.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Jiminny · Membrane","depth":4,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"console.getmembrane.com","depth":4,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Jiminny · Membrane","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny · Membrane","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Element Selectors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Element Selectors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"API Errors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"API Errors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"WORKSPACE ELEMENTS","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"WORKSPACE ELEMENTS","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connections Show subpages for Connections","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connections","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connections","depth":14,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"List connections GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connections","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connection PATCH","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connection PUT","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh connection credentials POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh connection credentials","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection logs GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection logs","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection dependencies GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection dependencies","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connection GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Restore connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Restore connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Archive connection DEL","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Archive connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connectors Hide subpages for Connectors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connectors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connectors","depth":14,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Connector Types Hide subpages for Connector Types","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Types","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connector Types","depth":16,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Client Credentials","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Client Credentials","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Token","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane Token","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth1","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth1","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth2","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth2","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Auth Proxy","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Auth Proxy","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connector Functions Show subpages for Connector Functions","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Functions","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connector Functions","depth":16,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Get Credentials from Connection Parameters","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get Credentials from Connection Parameters","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Make API Client","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Make API Client","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh Credentials","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh Credentials","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Disconnect","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Disconnect","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Universal Data Models","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Universal Data Models","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List connectors GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connectors","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List public connectors GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-5567825423644768547
|
1859033972171518540
|
idle
|
accessibility
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET...
|
NULL
|
|
47310
|
NULL
|
0
|
2026-04-17T11:24:44.812934+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425084812_m2.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET
List public connectors
GET
Get connector GET
Get connector
GET
Create connector POST
Create connector
POST
Patch connector PATCH
Patch connector
PATCH
Delete connector DEL
Delete connector
DEL
Download connector GET
Download connector
GET
Upload connector POST
Upload connector
POST
Import connector POST
Import connector
POST
Clone connector POST
Clone connector
POST
Get connector versions GET
Get connector versions
GET
Publish connector version POST
Publish connector version
POST
Update connector completely PUT
Update connector completely
PUT
Get a list of connector files GET
Get a list of connector files
GET
Get connector file by path GET
Get connector file by path
GET
Update connector file PUT
Update connector file
PUT
Delete connector file DEL
Delete connector file
DEL
Delete connector directory DEL
Delete connector directory
DEL
Export connector as zip file GET
Export connector as zip file
GET
Export connector as JSON GET
Export connector as JSON
GET
Integrations Show subpages for Integrations
Integrations
Show subpages for Integrations...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Jiminny · Membrane","depth":4,"bounds":{"left":0.09804688,"top":0.37430555,"width":0.04296875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"console.getmembrane.com","depth":4,"bounds":{"left":0.09804688,"top":0.38402778,"width":0.05546875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"bounds":{"left":0.0,"top":0.33888888,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"bounds":{"left":0.015625,"top":0.34861112,"width":0.021875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.34513888,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Jiminny · Membrane","depth":4,"bounds":{"left":0.0,"top":0.3673611,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny · Membrane","depth":5,"bounds":{"left":0.015625,"top":0.37708333,"width":0.041015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.37361112,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.39722222,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"bounds":{"left":0.09765625,"top":0.052083332,"width":0.048828125,"height":0.020833334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"bounds":{"left":0.1,"top":0.056944445,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"bounds":{"left":0.1015625,"top":0.048611112,"width":0.05078125,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"bounds":{"left":0.16015625,"top":0.048611112,"width":0.02421875,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"bounds":{"left":0.16132812,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"bounds":{"left":0.16992188,"top":0.05625,"width":0.01328125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"bounds":{"left":0.1921875,"top":0.048611112,"width":0.048046876,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"bounds":{"left":0.19335938,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"bounds":{"left":0.20195313,"top":0.05625,"width":0.037109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"bounds":{"left":0.90117186,"top":0.052083332,"width":0.05859375,"height":0.020833334},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"bounds":{"left":0.903125,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"bounds":{"left":0.91132814,"top":0.05625,"width":0.017578125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"bounds":{"left":0.96367186,"top":0.052083332,"width":0.024609376,"height":0.020833334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"bounds":{"left":0.96796876,"top":0.05625,"width":0.016015625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"bounds":{"left":0.099609375,"top":0.097222224,"width":0.09765625,"height":0.020833334},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"bounds":{"left":0.099609375,"top":0.14166667,"width":0.09765625,"height":0.011111111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"bounds":{"left":0.103515625,"top":0.1423611,"width":0.02578125,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"bounds":{"left":0.099609375,"top":0.16041666,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"bounds":{"left":0.103515625,"top":0.16597222,"width":0.037109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Element Selectors","depth":13,"bounds":{"left":0.099609375,"top":0.18333334,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Element Selectors","depth":15,"bounds":{"left":0.103515625,"top":0.18888889,"width":0.04609375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"API Errors","depth":13,"bounds":{"left":0.099609375,"top":0.20625,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"API Errors","depth":15,"bounds":{"left":0.103515625,"top":0.21180555,"width":0.025390625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"WORKSPACE ELEMENTS","depth":11,"bounds":{"left":0.099609375,"top":0.24930556,"width":0.09765625,"height":0.011111111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"WORKSPACE ELEMENTS","depth":12,"bounds":{"left":0.103515625,"top":0.25,"width":0.058203124,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connections Show subpages for Connections","depth":13,"bounds":{"left":0.099609375,"top":0.26805556,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connections","depth":15,"bounds":{"left":0.103515625,"top":0.2736111,"width":0.03203125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connections","depth":14,"bounds":{"left":0.1890625,"top":0.2736111,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"List connections GET","depth":15,"bounds":{"left":0.103515625,"top":0.28541666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connections","depth":17,"bounds":{"left":0.107421875,"top":0.29097223,"width":0.041796874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.2923611,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection GET","depth":15,"bounds":{"left":0.103515625,"top":0.30833334,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection","depth":17,"bounds":{"left":0.107421875,"top":0.31388888,"width":0.0390625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.31527779,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.33125,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connection","depth":17,"bounds":{"left":0.107421875,"top":0.33680555,"width":0.046875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.33819443,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connection PATCH","depth":15,"bounds":{"left":0.103515625,"top":0.35416666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connection","depth":17,"bounds":{"left":0.107421875,"top":0.35972223,"width":0.04453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"bounds":{"left":0.18085937,"top":0.3611111,"width":0.01328125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connection PUT","depth":15,"bounds":{"left":0.103515625,"top":0.37708333,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connection","depth":17,"bounds":{"left":0.107421875,"top":0.3826389,"width":0.0484375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"bounds":{"left":0.18320313,"top":0.38402778,"width":0.00859375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.4,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test connection","depth":17,"bounds":{"left":0.107421875,"top":0.40555555,"width":0.040625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.40694445,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh connection credentials POST","depth":15,"bounds":{"left":0.103515625,"top":0.42291668,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh connection credentials","depth":17,"bounds":{"left":0.107421875,"top":0.42847222,"width":0.049609374,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.4298611,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection logs GET","depth":15,"bounds":{"left":0.103515625,"top":0.45972222,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection logs","depth":17,"bounds":{"left":0.107421875,"top":0.4652778,"width":0.051171876,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.46666667,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection dependencies GET","depth":15,"bounds":{"left":0.103515625,"top":0.4826389,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection dependencies","depth":17,"bounds":{"left":0.107421875,"top":0.48819444,"width":0.0390625,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.48958334,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connection GET","depth":15,"bounds":{"left":0.103515625,"top":0.51944447,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connection","depth":17,"bounds":{"left":0.107421875,"top":0.525,"width":0.046484374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.5263889,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Restore connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.54236114,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Restore connection","depth":17,"bounds":{"left":0.107421875,"top":0.54791665,"width":0.049609374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.54930556,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Archive connection DEL","depth":15,"bounds":{"left":0.103515625,"top":0.56527776,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Archive connection","depth":17,"bounds":{"left":0.107421875,"top":0.5708333,"width":0.04921875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"bounds":{"left":0.18359375,"top":0.57222223,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connectors Hide subpages for Connectors","depth":13,"bounds":{"left":0.099609375,"top":0.29097223,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connectors","depth":15,"bounds":{"left":0.103515625,"top":0.29652777,"width":0.0296875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connectors","depth":14,"bounds":{"left":0.1890625,"top":0.29652777,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Connector Types Hide subpages for Connector Types","depth":15,"bounds":{"left":0.103515625,"top":0.31388888,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Types","depth":17,"bounds":{"left":0.107421875,"top":0.31944445,"width":0.04375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connector Types","depth":16,"bounds":{"left":0.1890625,"top":0.31944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Client Credentials","depth":17,"bounds":{"left":0.107421875,"top":0.33680555,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Client Credentials","depth":19,"bounds":{"left":0.111328125,"top":0.34236112,"width":0.0453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Token","depth":17,"bounds":{"left":0.107421875,"top":0.35972223,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane Token","depth":19,"bounds":{"left":0.111328125,"top":0.36527777,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth1","depth":17,"bounds":{"left":0.107421875,"top":0.3826389,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth1","depth":19,"bounds":{"left":0.111328125,"top":0.38819444,"width":0.018359374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth2","depth":17,"bounds":{"left":0.107421875,"top":0.40555555,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth2","depth":19,"bounds":{"left":0.111328125,"top":0.41111112,"width":0.019140625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Auth Proxy","depth":17,"bounds":{"left":0.107421875,"top":0.42847222,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Auth Proxy","depth":19,"bounds":{"left":0.111328125,"top":0.4340278,"width":0.027734375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connector Functions Show subpages for Connector Functions","depth":15,"bounds":{"left":0.103515625,"top":0.45277777,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Functions","depth":17,"bounds":{"left":0.107421875,"top":0.45833334,"width":0.053515624,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connector Functions","depth":16,"bounds":{"left":0.1890625,"top":0.45833334,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Get Credentials from Connection Parameters","depth":17,"bounds":{"left":0.107421875,"top":0.47013888,"width":0.08984375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get Credentials from Connection Parameters","depth":19,"bounds":{"left":0.111328125,"top":0.47569445,"width":0.083984375,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Make API Client","depth":17,"bounds":{"left":0.107421875,"top":0.5069444,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Make API Client","depth":19,"bounds":{"left":0.111328125,"top":0.5125,"width":0.040234376,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh Credentials","depth":17,"bounds":{"left":0.107421875,"top":0.5298611,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh Credentials","depth":19,"bounds":{"left":0.111328125,"top":0.53541666,"width":0.050390624,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test","depth":17,"bounds":{"left":0.107421875,"top":0.55277777,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test","depth":19,"bounds":{"left":0.111328125,"top":0.55833334,"width":0.0109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Disconnect","depth":17,"bounds":{"left":0.107421875,"top":0.57569444,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Disconnect","depth":19,"bounds":{"left":0.111328125,"top":0.58125,"width":0.02890625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Universal Data Models","depth":15,"bounds":{"left":0.103515625,"top":0.47569445,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Universal Data Models","depth":17,"bounds":{"left":0.107421875,"top":0.48125,"width":0.05703125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List connectors GET","depth":15,"bounds":{"left":0.103515625,"top":0.49861112,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connectors","depth":17,"bounds":{"left":0.107421875,"top":0.50416666,"width":0.039453126,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.50555557,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List public connectors GET","depth":15,"bounds":{"left":0.103515625,"top":0.52152777,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List public connectors","depth":17,"bounds":{"left":0.107421875,"top":0.52708334,"width":0.056640625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.52847224,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector GET","depth":15,"bounds":{"left":0.103515625,"top":0.54444444,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector","depth":17,"bounds":{"left":0.107421875,"top":0.55,"width":0.03671875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.55138886,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.5673611,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connector","depth":17,"bounds":{"left":0.107421875,"top":0.5729167,"width":0.04453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.57430553,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connector PATCH","depth":15,"bounds":{"left":0.103515625,"top":0.5902778,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connector","depth":17,"bounds":{"left":0.107421875,"top":0.59583336,"width":0.041796874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"bounds":{"left":0.18085937,"top":0.5972222,"width":0.01328125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Delete connector DEL","depth":15,"bounds":{"left":0.103515625,"top":0.61319447,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Delete connector","depth":17,"bounds":{"left":0.107421875,"top":0.61875,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"bounds":{"left":0.18359375,"top":0.6201389,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Download connector GET","depth":15,"bounds":{"left":0.103515625,"top":0.63611114,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Download connector","depth":17,"bounds":{"left":0.107421875,"top":0.64166665,"width":0.052734375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.64305556,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Upload connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.65902776,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Upload connector","depth":17,"bounds":{"left":0.107421875,"top":0.6645833,"width":0.045703124,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.66597223,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Import connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.68194443,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Import connector","depth":17,"bounds":{"left":0.107421875,"top":0.6875,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.6888889,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Clone connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.7048611,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Clone connector","depth":17,"bounds":{"left":0.107421875,"top":0.7104167,"width":0.0421875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.7118056,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector versions GET","depth":15,"bounds":{"left":0.103515625,"top":0.7277778,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector versions","depth":17,"bounds":{"left":0.107421875,"top":0.73333335,"width":0.059375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.7347222,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Publish connector version POST","depth":15,"bounds":{"left":0.103515625,"top":0.75069445,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Publish connector version","depth":17,"bounds":{"left":0.107421875,"top":0.75625,"width":0.06601562,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.7576389,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connector completely PUT","depth":15,"bounds":{"left":0.103515625,"top":0.7736111,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connector completely","depth":17,"bounds":{"left":0.107421875,"top":0.77916664,"width":0.04609375,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"bounds":{"left":0.18320313,"top":0.78055555,"width":0.00859375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get a list of connector files GET","depth":15,"bounds":{"left":0.103515625,"top":0.81041664,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get a list of connector files","depth":17,"bounds":{"left":0.107421875,"top":0.8159722,"width":0.06875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.8173611,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector file by path GET","depth":15,"bounds":{"left":0.103515625,"top":0.8333333,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector file by path","depth":17,"bounds":{"left":0.107421875,"top":0.8388889,"width":0.06640625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.8402778,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connector file PUT","depth":15,"bounds":{"left":0.103515625,"top":0.85625,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connector file","depth":17,"bounds":{"left":0.107421875,"top":0.86180556,"width":0.05546875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"bounds":{"left":0.18320313,"top":0.86319447,"width":0.00859375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Delete connector file DEL","depth":15,"bounds":{"left":0.103515625,"top":0.87916666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Delete connector file","depth":17,"bounds":{"left":0.107421875,"top":0.88472223,"width":0.053125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"bounds":{"left":0.18359375,"top":0.88611114,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Delete connector directory DEL","depth":15,"bounds":{"left":0.103515625,"top":0.90208334,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Delete connector directory","depth":17,"bounds":{"left":0.107421875,"top":0.9076389,"width":0.068359375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"bounds":{"left":0.18359375,"top":0.90902776,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connector as zip file GET","depth":15,"bounds":{"left":0.103515625,"top":0.925,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connector as zip file","depth":17,"bounds":{"left":0.107421875,"top":0.9305556,"width":0.060546875,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.93194443,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connector as JSON GET","depth":15,"bounds":{"left":0.103515625,"top":0.9618056,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connector as JSON","depth":17,"bounds":{"left":0.107421875,"top":0.9673611,"width":0.06757812,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.96875,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Integrations Show subpages for Integrations","depth":13,"bounds":{"left":0.099609375,"top":0.9861111,"width":0.09765625,"height":0.0138888955},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Integrations","depth":15,"bounds":{"left":0.103515625,"top":0.9916667,"width":0.03046875,"height":0.008333325},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Integrations","depth":14,"bounds":{"left":0.1890625,"top":0.9916667,"width":0.00625,"height":0.008333325},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2946507518247493010
|
-446809511585367476
|
idle
|
accessibility
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET
List public connectors
GET
Get connector GET
Get connector
GET
Create connector POST
Create connector
POST
Patch connector PATCH
Patch connector
PATCH
Delete connector DEL
Delete connector
DEL
Download connector GET
Download connector
GET
Upload connector POST
Upload connector
POST
Import connector POST
Import connector
POST
Clone connector POST
Clone connector
POST
Get connector versions GET
Get connector versions
GET
Publish connector version POST
Publish connector version
POST
Update connector completely PUT
Update connector completely
PUT
Get a list of connector files GET
Get a list of connector files
GET
Get connector file by path GET
Get connector file by path
GET
Update connector file PUT
Update connector file
PUT
Delete connector file DEL
Delete connector file
DEL
Delete connector directory DEL
Delete connector directory
DEL
Export connector as zip file GET
Export connector as zip file
GET
Export connector as JSON GET
Export connector as JSON
GET
Integrations Show subpages for Integrations
Integrations
Show subpages for Integrations...
|
NULL
|
|
47311
|
999
|
0
|
2026-04-17T11:25:08.882872+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425108882_m1.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET
List public connectors
GET
Get connector GET
Get connector
GET
Create connector POST
Create connector
POST
Patch connector PATCH
Patch connector
PATCH
Delete connector DEL
Delete connector
DEL
Download connector GET
Download connector
GET
Upload connector POST
Upload connector
POST
Import connector POST
Import connector
POST
Clone connector POST
Clone connector
POST
Get connector versions GET
Get connector versions
GET
Publish connector version POST
Publish connector version
POST
Update connector completely PUT
Update connector completely
PUT
Get a list of connector files GET
Get a list of connector files
GET
Get connector file by path GET
Get connector file by path
GET
Update connector file PUT
Update connector file
PUT
Delete connector file DEL
Delete connector file
DEL
Delete connector directory DEL
Delete connector directory
DEL
Export connector as zip file GET
Export connector as zip file
GET
Export connector as JSON GET
Export connector as JSON
GET
Integrations Show subpages for Integrations
Integrations
Show subpages for Integrations
Integrations UI Show subpages for Integrations UI
Integrations UI
Show subpages for Integrations UI
Custom Integrations Catalog UI
Custom Integrations Catalog UI
Custom Integration UI...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Jiminny · Membrane","depth":4,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"console.getmembrane.com","depth":4,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Jiminny · Membrane","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny · Membrane","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Element Selectors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Element Selectors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"API Errors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"API Errors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"WORKSPACE ELEMENTS","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"WORKSPACE ELEMENTS","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connections Show subpages for Connections","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connections","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connections","depth":14,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"List connections GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connections","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connection PATCH","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connection PUT","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh connection credentials POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh connection credentials","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection logs GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection logs","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection dependencies GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection dependencies","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connection GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Restore connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Restore connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Archive connection DEL","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Archive connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connectors Hide subpages for Connectors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connectors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connectors","depth":14,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Connector Types Hide subpages for Connector Types","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Types","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connector Types","depth":16,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Client Credentials","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Client Credentials","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Token","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane Token","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth1","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth1","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth2","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth2","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Auth Proxy","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Auth Proxy","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connector Functions Show subpages for Connector Functions","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Functions","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connector Functions","depth":16,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Get Credentials from Connection Parameters","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get Credentials from Connection Parameters","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Make API Client","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Make API Client","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh Credentials","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh Credentials","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Disconnect","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Disconnect","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Universal Data Models","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Universal Data Models","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List connectors GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connectors","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List public connectors GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List public connectors","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connector POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connector","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connector PATCH","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connector","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Delete connector DEL","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Delete connector","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Download connector GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Download connector","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Upload connector POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Upload connector","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Import connector POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Import connector","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Clone connector POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Clone connector","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector versions GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector versions","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Publish connector version POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Publish connector version","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connector completely PUT","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connector completely","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get a list of connector files GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get a list of connector files","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector file by path GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector file by path","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connector file PUT","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connector file","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Delete connector file DEL","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Delete connector file","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Delete connector directory DEL","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Delete connector directory","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connector as zip file GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connector as zip file","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connector as JSON GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connector as JSON","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.0,"top":0.0,"width":0.013888889,"height":0.014444444},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Integrations Show subpages for Integrations","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Integrations","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Integrations","depth":14,"bounds":{"left":0.0,"top":0.0,"width":0.011111111,"height":0.017777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Integrations UI Show subpages for Integrations UI","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Integrations UI","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Integrations UI","depth":16,"bounds":{"left":0.0,"top":0.014444444,"width":0.011111111,"height":0.017777778},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Custom Integrations Catalog UI","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Custom Integrations Catalog UI","depth":19,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Custom Integration UI","depth":17,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
2191948217862518263
|
8767555321686145612
|
idle
|
accessibility
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET
List public connectors
GET
Get connector GET
Get connector
GET
Create connector POST
Create connector
POST
Patch connector PATCH
Patch connector
PATCH
Delete connector DEL
Delete connector
DEL
Download connector GET
Download connector
GET
Upload connector POST
Upload connector
POST
Import connector POST
Import connector
POST
Clone connector POST
Clone connector
POST
Get connector versions GET
Get connector versions
GET
Publish connector version POST
Publish connector version
POST
Update connector completely PUT
Update connector completely
PUT
Get a list of connector files GET
Get a list of connector files
GET
Get connector file by path GET
Get connector file by path
GET
Update connector file PUT
Update connector file
PUT
Delete connector file DEL
Delete connector file
DEL
Delete connector directory DEL
Delete connector directory
DEL
Export connector as zip file GET
Export connector as zip file
GET
Export connector as JSON GET
Export connector as JSON
GET
Integrations Show subpages for Integrations
Integrations
Show subpages for Integrations
Integrations UI Show subpages for Integrations UI
Integrations UI
Show subpages for Integrations UI
Custom Integrations Catalog UI
Custom Integrations Catalog UI
Custom Integration UI...
|
47309
|
|
47312
|
1000
|
0
|
2026-04-17T11:25:15.212484+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425115212_m2.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET
List public connectors
GET
Get connector GET
Get connector
GET
Create connector POST
Create connector
POST
Patch connector PATCH
Patch connector
PATCH
Delete connector DEL
Delete connector
DEL
Download connector GET
Download connector
GET
Upload connector POST
Upload connector
POST
Import connector POST
Import connector
POST
Clone connector POST...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Jiminny · Membrane","depth":4,"bounds":{"left":0.09804688,"top":0.37430555,"width":0.04296875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"console.getmembrane.com","depth":4,"bounds":{"left":0.09804688,"top":0.38402778,"width":0.05546875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"bounds":{"left":0.0,"top":0.33888888,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"bounds":{"left":0.015625,"top":0.34861112,"width":0.021875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.34513888,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Jiminny · Membrane","depth":4,"bounds":{"left":0.0,"top":0.3673611,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny · Membrane","depth":5,"bounds":{"left":0.015625,"top":0.37708333,"width":0.041015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.37361112,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.39722222,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"bounds":{"left":0.09765625,"top":0.052083332,"width":0.048828125,"height":0.020833334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"bounds":{"left":0.1,"top":0.056944445,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"bounds":{"left":0.1015625,"top":0.048611112,"width":0.05078125,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"bounds":{"left":0.16015625,"top":0.048611112,"width":0.02421875,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"bounds":{"left":0.16132812,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"bounds":{"left":0.16992188,"top":0.05625,"width":0.01328125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"bounds":{"left":0.1921875,"top":0.048611112,"width":0.048046876,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"bounds":{"left":0.19335938,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"bounds":{"left":0.20195313,"top":0.05625,"width":0.037109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"bounds":{"left":0.90117186,"top":0.052083332,"width":0.05859375,"height":0.020833334},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"bounds":{"left":0.903125,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"bounds":{"left":0.91132814,"top":0.05625,"width":0.017578125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"bounds":{"left":0.96367186,"top":0.052083332,"width":0.024609376,"height":0.020833334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"bounds":{"left":0.96796876,"top":0.05625,"width":0.016015625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"bounds":{"left":0.099609375,"top":0.097222224,"width":0.09765625,"height":0.020833334},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"bounds":{"left":0.099609375,"top":0.14166667,"width":0.09765625,"height":0.011111111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"bounds":{"left":0.103515625,"top":0.1423611,"width":0.02578125,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"bounds":{"left":0.099609375,"top":0.16041666,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"bounds":{"left":0.103515625,"top":0.16597222,"width":0.037109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Element Selectors","depth":13,"bounds":{"left":0.099609375,"top":0.18333334,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Element Selectors","depth":15,"bounds":{"left":0.103515625,"top":0.18888889,"width":0.04609375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"API Errors","depth":13,"bounds":{"left":0.099609375,"top":0.20625,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"API Errors","depth":15,"bounds":{"left":0.103515625,"top":0.21180555,"width":0.025390625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"WORKSPACE ELEMENTS","depth":11,"bounds":{"left":0.099609375,"top":0.24930556,"width":0.09765625,"height":0.011111111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"WORKSPACE ELEMENTS","depth":12,"bounds":{"left":0.103515625,"top":0.25,"width":0.058203124,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connections Show subpages for Connections","depth":13,"bounds":{"left":0.099609375,"top":0.26805556,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connections","depth":15,"bounds":{"left":0.103515625,"top":0.2736111,"width":0.03203125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connections","depth":14,"bounds":{"left":0.1890625,"top":0.2736111,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"List connections GET","depth":15,"bounds":{"left":0.103515625,"top":0.28541666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connections","depth":17,"bounds":{"left":0.107421875,"top":0.29097223,"width":0.041796874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.2923611,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection GET","depth":15,"bounds":{"left":0.103515625,"top":0.30833334,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection","depth":17,"bounds":{"left":0.107421875,"top":0.31388888,"width":0.0390625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.31527779,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.33125,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connection","depth":17,"bounds":{"left":0.107421875,"top":0.33680555,"width":0.046875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.33819443,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connection PATCH","depth":15,"bounds":{"left":0.103515625,"top":0.35416666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connection","depth":17,"bounds":{"left":0.107421875,"top":0.35972223,"width":0.04453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"bounds":{"left":0.18085937,"top":0.3611111,"width":0.01328125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connection PUT","depth":15,"bounds":{"left":0.103515625,"top":0.37708333,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connection","depth":17,"bounds":{"left":0.107421875,"top":0.3826389,"width":0.0484375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"bounds":{"left":0.18320313,"top":0.38402778,"width":0.00859375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.4,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test connection","depth":17,"bounds":{"left":0.107421875,"top":0.40555555,"width":0.040625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.40694445,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh connection credentials POST","depth":15,"bounds":{"left":0.103515625,"top":0.42291668,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh connection credentials","depth":17,"bounds":{"left":0.107421875,"top":0.42847222,"width":0.049609374,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.4298611,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection logs GET","depth":15,"bounds":{"left":0.103515625,"top":0.45972222,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection logs","depth":17,"bounds":{"left":0.107421875,"top":0.4652778,"width":0.051171876,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.46666667,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection dependencies GET","depth":15,"bounds":{"left":0.103515625,"top":0.4826389,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection dependencies","depth":17,"bounds":{"left":0.107421875,"top":0.48819444,"width":0.0390625,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.48958334,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connection GET","depth":15,"bounds":{"left":0.103515625,"top":0.51944447,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connection","depth":17,"bounds":{"left":0.107421875,"top":0.525,"width":0.046484374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.5263889,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Restore connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.54236114,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Restore connection","depth":17,"bounds":{"left":0.107421875,"top":0.54791665,"width":0.049609374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.54930556,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Archive connection DEL","depth":15,"bounds":{"left":0.103515625,"top":0.56527776,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Archive connection","depth":17,"bounds":{"left":0.107421875,"top":0.5708333,"width":0.04921875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"bounds":{"left":0.18359375,"top":0.57222223,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connectors Hide subpages for Connectors","depth":13,"bounds":{"left":0.099609375,"top":0.29097223,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connectors","depth":15,"bounds":{"left":0.103515625,"top":0.29652777,"width":0.0296875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connectors","depth":14,"bounds":{"left":0.1890625,"top":0.29652777,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Connector Types Hide subpages for Connector Types","depth":15,"bounds":{"left":0.103515625,"top":0.31388888,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Types","depth":17,"bounds":{"left":0.107421875,"top":0.31944445,"width":0.04375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Hide subpages for Connector Types","depth":16,"bounds":{"left":0.1890625,"top":0.31944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXLink","text":"Client Credentials","depth":17,"bounds":{"left":0.107421875,"top":0.33680555,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Client Credentials","depth":19,"bounds":{"left":0.111328125,"top":0.34236112,"width":0.0453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Token","depth":17,"bounds":{"left":0.107421875,"top":0.35972223,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Membrane Token","depth":19,"bounds":{"left":0.111328125,"top":0.36527777,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth1","depth":17,"bounds":{"left":0.107421875,"top":0.3826389,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth1","depth":19,"bounds":{"left":0.111328125,"top":0.38819444,"width":0.018359374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"OAuth2","depth":17,"bounds":{"left":0.107421875,"top":0.40555555,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"OAuth2","depth":19,"bounds":{"left":0.111328125,"top":0.41111112,"width":0.019140625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Auth Proxy","depth":17,"bounds":{"left":0.107421875,"top":0.42847222,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Auth Proxy","depth":19,"bounds":{"left":0.111328125,"top":0.4340278,"width":0.027734375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connector Functions Show subpages for Connector Functions","depth":15,"bounds":{"left":0.103515625,"top":0.45277777,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connector Functions","depth":17,"bounds":{"left":0.107421875,"top":0.45833334,"width":0.053515624,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connector Functions","depth":16,"bounds":{"left":0.1890625,"top":0.45833334,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Get Credentials from Connection Parameters","depth":17,"bounds":{"left":0.107421875,"top":0.47013888,"width":0.08984375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get Credentials from Connection Parameters","depth":19,"bounds":{"left":0.111328125,"top":0.47569445,"width":0.083984375,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Make API Client","depth":17,"bounds":{"left":0.107421875,"top":0.5069444,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Make API Client","depth":19,"bounds":{"left":0.111328125,"top":0.5125,"width":0.040234376,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh Credentials","depth":17,"bounds":{"left":0.107421875,"top":0.5298611,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh Credentials","depth":19,"bounds":{"left":0.111328125,"top":0.53541666,"width":0.050390624,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test","depth":17,"bounds":{"left":0.107421875,"top":0.55277777,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test","depth":19,"bounds":{"left":0.111328125,"top":0.55833334,"width":0.0109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Disconnect","depth":17,"bounds":{"left":0.107421875,"top":0.57569444,"width":0.08984375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Disconnect","depth":19,"bounds":{"left":0.111328125,"top":0.58125,"width":0.02890625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Universal Data Models","depth":15,"bounds":{"left":0.103515625,"top":0.47569445,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Universal Data Models","depth":17,"bounds":{"left":0.107421875,"top":0.48125,"width":0.05703125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List connectors GET","depth":15,"bounds":{"left":0.103515625,"top":0.49861112,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connectors","depth":17,"bounds":{"left":0.107421875,"top":0.50416666,"width":0.039453126,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.50555557,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"List public connectors GET","depth":15,"bounds":{"left":0.103515625,"top":0.52152777,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List public connectors","depth":17,"bounds":{"left":0.107421875,"top":0.52708334,"width":0.056640625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.52847224,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connector GET","depth":15,"bounds":{"left":0.103515625,"top":0.54444444,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connector","depth":17,"bounds":{"left":0.107421875,"top":0.55,"width":0.03671875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.55138886,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.5673611,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connector","depth":17,"bounds":{"left":0.107421875,"top":0.5729167,"width":0.04453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.57430553,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connector PATCH","depth":15,"bounds":{"left":0.103515625,"top":0.5902778,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connector","depth":17,"bounds":{"left":0.107421875,"top":0.59583336,"width":0.041796874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"bounds":{"left":0.18085937,"top":0.5972222,"width":0.01328125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Delete connector DEL","depth":15,"bounds":{"left":0.103515625,"top":0.61319447,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Delete connector","depth":17,"bounds":{"left":0.107421875,"top":0.61875,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"DEL","depth":16,"bounds":{"left":0.18359375,"top":0.6201389,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Download connector GET","depth":15,"bounds":{"left":0.103515625,"top":0.63611114,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Download connector","depth":17,"bounds":{"left":0.107421875,"top":0.64166665,"width":0.052734375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.64305556,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Upload connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.65902776,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Upload connector","depth":17,"bounds":{"left":0.107421875,"top":0.6645833,"width":0.045703124,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.66597223,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Import connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.68194443,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Import connector","depth":17,"bounds":{"left":0.107421875,"top":0.6875,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.6888889,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Clone connector POST","depth":15,"bounds":{"left":0.103515625,"top":0.7048611,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
4592500321355579666
|
1823039809786526276
|
idle
|
accessibility
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL
Archive connection
DEL
Connectors Hide subpages for Connectors
Connectors
Hide subpages for Connectors
Connector Types Hide subpages for Connector Types
Connector Types
Hide subpages for Connector Types
Client Credentials
Client Credentials
Membrane Token
Membrane Token
OAuth1
OAuth1
OAuth2
OAuth2
Auth Proxy
Auth Proxy
Connector Functions Show subpages for Connector Functions
Connector Functions
Show subpages for Connector Functions
Get Credentials from Connection Parameters
Get Credentials from Connection Parameters
Make API Client
Make API Client
Refresh Credentials
Refresh Credentials
Test
Test
Disconnect
Disconnect
Universal Data Models
Universal Data Models
List connectors GET
List connectors
GET
List public connectors GET
List public connectors
GET
Get connector GET
Get connector
GET
Create connector POST
Create connector
POST
Patch connector PATCH
Patch connector
PATCH
Delete connector DEL
Delete connector
DEL
Download connector GET
Download connector
GET
Upload connector POST
Upload connector
POST
Import connector POST
Import connector
POST
Clone connector POST...
|
47310
|
|
47327
|
NULL
|
0
|
2026-04-17T11:29:10.966876+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425350966_m1.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Jiminny · Membrane","depth":4,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"console.getmembrane.com","depth":4,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Jiminny · Membrane","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny · Membrane","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Element Selectors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Element Selectors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"API Errors","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"API Errors","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"WORKSPACE ELEMENTS","depth":11,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"WORKSPACE ELEMENTS","depth":12,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connections Show subpages for Connections","depth":13,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connections","depth":15,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connections","depth":14,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"List connections GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connections","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connection PATCH","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connection PUT","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh connection credentials POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh connection credentials","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection logs GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection logs","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection dependencies GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection dependencies","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connection GET","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Restore connection POST","depth":15,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Restore connection","depth":17,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
4438693934993446109
|
6398556292618697292
|
idle
|
accessibility
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection...
|
47325
|
|
47328
|
NULL
|
0
|
2026-04-17T11:29:18.631308+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425358631_m2.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Jiminny · Membrane","depth":4,"bounds":{"left":0.09804688,"top":0.37430555,"width":0.04296875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"console.getmembrane.com","depth":4,"bounds":{"left":0.09804688,"top":0.38402778,"width":0.05546875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"bounds":{"left":0.0,"top":0.33888888,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"bounds":{"left":0.015625,"top":0.34861112,"width":0.021875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.34513888,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Jiminny · Membrane","depth":4,"bounds":{"left":0.0,"top":0.3673611,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny · Membrane","depth":5,"bounds":{"left":0.015625,"top":0.37708333,"width":0.041015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.37361112,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.39722222,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Jump to Content","depth":11,"bounds":{"left":0.09765625,"top":0.052083332,"width":0.048828125,"height":0.020833334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jump to Content","depth":12,"bounds":{"left":0.1,"top":0.056944445,"width":0.044140626,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Membrane Docs","depth":11,"bounds":{"left":0.1015625,"top":0.048611112,"width":0.05078125,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":" Docs","depth":11,"bounds":{"left":0.16015625,"top":0.048611112,"width":0.02421875,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"bounds":{"left":0.16132812,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Docs","depth":13,"bounds":{"left":0.16992188,"top":0.05625,"width":0.01328125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":" API Reference","depth":11,"bounds":{"left":0.1921875,"top":0.048611112,"width":0.048046876,"height":0.027083334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":13,"bounds":{"left":0.19335938,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"API Reference","depth":13,"bounds":{"left":0.20195313,"top":0.05625,"width":0.037109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search ⌘k","depth":10,"bounds":{"left":0.90117186,"top":0.052083332,"width":0.05859375,"height":0.020833334},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"","depth":11,"bounds":{"left":0.903125,"top":0.056944445,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Search","depth":12,"bounds":{"left":0.91132814,"top":0.05625,"width":0.017578125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Log In","depth":10,"bounds":{"left":0.96367186,"top":0.052083332,"width":0.024609376,"height":0.020833334},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Log In","depth":11,"bounds":{"left":0.96796876,"top":0.05625,"width":0.016015625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"JUMP TO","depth":10,"bounds":{"left":0.099609375,"top":0.097222224,"width":0.09765625,"height":0.020833334},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":true,"is_selected":false},{"role":"AXHeading","text":"OVERVIEW","depth":11,"bounds":{"left":0.099609375,"top":0.14166667,"width":0.09765625,"height":0.011111111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"OVERVIEW","depth":12,"bounds":{"left":0.103515625,"top":0.1423611,"width":0.02578125,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Authentication","depth":13,"bounds":{"left":0.099609375,"top":0.16041666,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Authentication","depth":15,"bounds":{"left":0.103515625,"top":0.16597222,"width":0.037109375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Element Selectors","depth":13,"bounds":{"left":0.099609375,"top":0.18333334,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Element Selectors","depth":15,"bounds":{"left":0.103515625,"top":0.18888889,"width":0.04609375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"API Errors","depth":13,"bounds":{"left":0.099609375,"top":0.20625,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"API Errors","depth":15,"bounds":{"left":0.103515625,"top":0.21180555,"width":0.025390625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"WORKSPACE ELEMENTS","depth":11,"bounds":{"left":0.099609375,"top":0.24930556,"width":0.09765625,"height":0.011111111},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"WORKSPACE ELEMENTS","depth":12,"bounds":{"left":0.103515625,"top":0.25,"width":0.058203124,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connections Show subpages for Connections","depth":13,"bounds":{"left":0.099609375,"top":0.26805556,"width":0.09765625,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connections","depth":15,"bounds":{"left":0.103515625,"top":0.2736111,"width":0.03203125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Show subpages for Connections","depth":14,"bounds":{"left":0.1890625,"top":0.2736111,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"List connections GET","depth":15,"bounds":{"left":0.103515625,"top":0.28541666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"List connections","depth":17,"bounds":{"left":0.107421875,"top":0.29097223,"width":0.041796874,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.2923611,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection GET","depth":15,"bounds":{"left":0.103515625,"top":0.30833334,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection","depth":17,"bounds":{"left":0.107421875,"top":0.31388888,"width":0.0390625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.31527779,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Create connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.33125,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Create connection","depth":17,"bounds":{"left":0.107421875,"top":0.33680555,"width":0.046875,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.33819443,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Patch connection PATCH","depth":15,"bounds":{"left":0.103515625,"top":0.35416666,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Patch connection","depth":17,"bounds":{"left":0.107421875,"top":0.35972223,"width":0.04453125,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PATCH","depth":16,"bounds":{"left":0.18085937,"top":0.3611111,"width":0.01328125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Update connection PUT","depth":15,"bounds":{"left":0.103515625,"top":0.37708333,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Update connection","depth":17,"bounds":{"left":0.107421875,"top":0.3826389,"width":0.0484375,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"PUT","depth":16,"bounds":{"left":0.18320313,"top":0.38402778,"width":0.00859375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.4,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test connection","depth":17,"bounds":{"left":0.107421875,"top":0.40555555,"width":0.040625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.40694445,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Refresh connection credentials POST","depth":15,"bounds":{"left":0.103515625,"top":0.42291668,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Refresh connection credentials","depth":17,"bounds":{"left":0.107421875,"top":0.42847222,"width":0.049609374,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.4298611,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection logs GET","depth":15,"bounds":{"left":0.103515625,"top":0.45972222,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection logs","depth":17,"bounds":{"left":0.107421875,"top":0.4652778,"width":0.051171876,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.46666667,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Get connection dependencies GET","depth":15,"bounds":{"left":0.103515625,"top":0.4826389,"width":0.09375,"height":0.036111113},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Get connection dependencies","depth":17,"bounds":{"left":0.107421875,"top":0.48819444,"width":0.0390625,"height":0.025694445},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.48958334,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Export connection GET","depth":15,"bounds":{"left":0.103515625,"top":0.51944447,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Export connection","depth":17,"bounds":{"left":0.107421875,"top":0.525,"width":0.046484374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"GET","depth":16,"bounds":{"left":0.18359375,"top":0.5263889,"width":0.0078125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Restore connection POST","depth":15,"bounds":{"left":0.103515625,"top":0.54236114,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Restore connection","depth":17,"bounds":{"left":0.107421875,"top":0.54791665,"width":0.049609374,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"POST","depth":16,"bounds":{"left":0.18203124,"top":0.54930556,"width":0.0109375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Archive connection DEL","depth":15,"bounds":{"left":0.103515625,"top":0.56527776,"width":0.09375,"height":0.022222223},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-6410721714148244440
|
-2824534269259367860
|
idle
|
accessibility
|
NULL
|
Jiminny · Membrane
console.getmembrane.com
Workers Jiminny · Membrane
console.getmembrane.com
Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Close tab
Jiminny · Membrane
Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Jump to Content
Jump to Content
Membrane Docs
Docs
Docs
API Reference
API Reference
Search ⌘k
Search
Log In
Log In
JUMP TO
OVERVIEW
OVERVIEW
Authentication
Authentication
Element Selectors
Element Selectors
API Errors
API Errors
WORKSPACE ELEMENTS
WORKSPACE ELEMENTS
Connections Show subpages for Connections
Connections
Show subpages for Connections
List connections GET
List connections
GET
Get connection GET
Get connection
GET
Create connection POST
Create connection
POST
Patch connection PATCH
Patch connection
PATCH
Update connection PUT
Update connection
PUT
Test connection POST
Test connection
POST
Refresh connection credentials POST
Refresh connection credentials
POST
Get connection logs GET
Get connection logs
GET
Get connection dependencies GET
Get connection dependencies
GET
Export connection GET
Export connection
GET
Restore connection POST
Restore connection
POST
Archive connection DEL...
|
47326
|
|
47329
|
1001
|
0
|
2026-04-17T11:32:14.247563+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425534247_m1.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
7928508828199755921
|
-2794737520899708348
|
click
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence...
|
NULL
|
|
47330
|
1002
|
0
|
2026-04-17T11:32:14.151598+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425534151_m2.jpg...
|
Firefox
|
Auth Proxy — Work
|
1
|
docs.getmembrane.com/reference/auth-proxy
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
5804020355574208802
|
-2385926751833284034
|
click
|
hybrid
|
NULL
|
Workers | Datadog
Firefox FileEoitViewHistory Book Workers | Datadog
Firefox FileEoitViewHistory Bookmarks ProfilesTools Window Help• == docs.getmembrane.com/reference/auth-proxyMembraneM Docs<> API ReferenceDevelopers | HubSpotJUMt 1OM'inbox (1,576) - lukas.kovalik@jiminM° 120216 is your HubSpot Log in CocOVERVIEWHutnenuicalioniFa CloudWatch | eu-west-1New TabElement SelectorsAPI Errorsz Configure SSH access to multipleWORKSPACE ELEMENIS. fix-cache-for-business-processes4 [JY-20692] Issue with reconnectir(8) JiminnyConnectionsConnectorsConnector TypesAuth ProxyCent Credentials'Jiminny - MembraneMemorane lokenOHULN I+ New TabOAuth2Auth ProxyConnector runctionsiUniversal Data ModelsList connectorsList public connectorsGet connectorCreate connectorPatch connectorDelete connectorDownload connectorUpload connectorImport connectorClone connectorGet connector versionsPulhlish connector vercionIUpdate connectorcompletelyGet a list of connector filesGet connector file by pathUpdate connector fileDelete connector fileDelete connector directoryExport connector as zipfileGETOExport connector as JSON GET< 40 ldl I Support Daily • in 28m100% CS& Fri 17 Apr 14:32:14• SearchlLog InWORKSPACE ELEMENTS > CONNECTORS > CONNECTOR TYPESAuth Proxy•† Ask Al vAuth Proxy lets you use OAuth credentials provided by Membrane without registering your own OAuth app.You typically don't need to use this authentication type yourself, but you may find it in pre-builtconnectors.When using Auth Proxy, you will not have access to the connection credentials.Example connector definition:YAML# Connector definition: Use Membrane-provided OAuth credentials (no custom OAuth appпесасалtype: auth-proxyproxyKey: auth-proxy-key@ Updated 30 days ago< OAuth2Connector Functions →Did this page help you? & Yes INo...
|
NULL
|
|
47382
|
NULL
|
0
|
2026-04-17T11:34:51.388894+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425691388_m1.jpg...
|
NULL
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpalol• Support Daily - in 26 mlAPP (-zsh)X4-zsh100% <47• ₴78Fri 17 Apr 14:34:511₴81ec2-user@ip-10-...• 88DOCKER• ₴1DEV (docker)• *2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-DutwAJ6x.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-CjPoT6NF.js:./public/vue-assets/assets/AskAnything-a4BpUaF5.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CtfldUq7.js:./public/vue-assets/assets/deal-view-DhouIWLw.js../public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWns-By9.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-BENebgvU.js./public/vue-assets/assets/StatusBadge-CmcY3nfX.js./public/vue-assets/assets/kiosk-1vhk4_89.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-DN-kVyxK.js../public/vue-assets/assets/ListView-POU6dSu7.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-DYH5MiIH.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMd0Dr.js../public/vue-assets/assets/sentry-c0Rhilsu.js:./public/vue-assets/assets/OrgSettingsLayout-ByQjX4wG.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-BH9MB7YC.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js./public/vue-assets/assets/team-insights-BqCZQtVc.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-XL9ZmWsU.js./public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CPycMtZF.js../public/vue-assets/assets/logged-in-layout-B_JDhk5y.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.26kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 28.48s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/Output0ptions.codeSplitting- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $U* Review screenp...gzip:9.38kBgz1p:10.18kBgzip:9.58kB9z1p:10.62kB9z1p:14.97kBgzip:12.70kBgzip:12.69kBgzip:14.34kBgz1p:16.46kBgzip:15.07kBgz1p:13.28kBgzip:20.09kBgzip:18.88kB9z1p:21.90kB921p:22.96kBgzip:22.64kBgzip:27.46kBgzip:gzip:28.16kB33.78kBgzip:38.71 kBgz1p:34.16 kBgzip:40.05kBgzip:36.72 kBgzip:43.03 kB9z1p:52.24kB9z1p:56.15kBgzip:67.85kBgzip:61.85kBgz1p:64.16kBgzip:60.31kB9z1p:77.21kBgz1p:103.86kBgzip:84.90kB9z1p:97.05kBgzip: 202.81kBgzip:72.53-kBgzip: 438.08 kB• [EMAIL]:73.94kBmap:93.18kBmap:78.74kBmap:115.18kBmap:173.20 kBmap:138.34kBmap:150.73kBmap:150.62kBmap:294.48kBmap:153.25kBmap:65..85kBmap:239.59kBmap:219.27kBmap:201.62kBmap:244.72kBmap:300.68kBmap:3,452.35kBmap:292.79kBmap:308.10kBmap:500.60 kBmap:258.56kBmap:410.48kBmap:266.15kBmap:516.67kBmap:831..82kBmap:623.43kBmap:836.88kBmap:684.87kBmap:1,108.20kBmap:475.61kBmap:959.96kBmap:1,245.28kBmap:849.05kBmap:792.41kBmap:3,016.64kBmap:436.62kBmaр: 6,283.55kBAPP...
|
NULL
|
-7096262296817934594
|
NULL
|
click
|
ocr
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpalol• Support Daily - in 26 mlAPP (-zsh)X4-zsh100% <47• ₴78Fri 17 Apr 14:34:511₴81ec2-user@ip-10-...• 88DOCKER• ₴1DEV (docker)• *2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-DutwAJ6x.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-CjPoT6NF.js:./public/vue-assets/assets/AskAnything-a4BpUaF5.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CtfldUq7.js:./public/vue-assets/assets/deal-view-DhouIWLw.js../public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWns-By9.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-BENebgvU.js./public/vue-assets/assets/StatusBadge-CmcY3nfX.js./public/vue-assets/assets/kiosk-1vhk4_89.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-DN-kVyxK.js../public/vue-assets/assets/ListView-POU6dSu7.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-DYH5MiIH.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMd0Dr.js../public/vue-assets/assets/sentry-c0Rhilsu.js:./public/vue-assets/assets/OrgSettingsLayout-ByQjX4wG.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-BH9MB7YC.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js./public/vue-assets/assets/team-insights-BqCZQtVc.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-XL9ZmWsU.js./public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CPycMtZF.js../public/vue-assets/assets/logged-in-layout-B_JDhk5y.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.26kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 28.48s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/Output0ptions.codeSplitting- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app/front-end (JY-20692-fix-integration-app-[API_KEY]) $U* Review screenp...gzip:9.38kBgz1p:10.18kBgzip:9.58kB9z1p:10.62kB9z1p:14.97kBgzip:12.70kBgzip:12.69kBgzip:14.34kBgz1p:16.46kBgzip:15.07kBgz1p:13.28kBgzip:20.09kBgzip:18.88kB9z1p:21.90kB921p:22.96kBgzip:22.64kBgzip:27.46kBgzip:gzip:28.16kB33.78kBgzip:38.71 kBgz1p:34.16 kBgzip:40.05kBgzip:36.72 kBgzip:43.03 kB9z1p:52.24kB9z1p:56.15kBgzip:67.85kBgzip:61.85kBgz1p:64.16kBgzip:60.31kB9z1p:77.21kBgz1p:103.86kBgzip:84.90kB9z1p:97.05kBgzip: 202.81kBgzip:72.53-kBgzip: 438.08 kB• [EMAIL]:73.94kBmap:93.18kBmap:78.74kBmap:115.18kBmap:173.20 kBmap:138.34kBmap:150.73kBmap:150.62kBmap:294.48kBmap:153.25kBmap:65..85kBmap:239.59kBmap:219.27kBmap:201.62kBmap:244.72kBmap:300.68kBmap:3,452.35kBmap:292.79kBmap:308.10kBmap:500.60 kBmap:258.56kBmap:410.48kBmap:266.15kBmap:516.67kBmap:831..82kBmap:623.43kBmap:836.88kBmap:684.87kBmap:1,108.20kBmap:475.61kBmap:959.96kBmap:1,245.28kBmap:849.05kBmap:792.41kBmap:3,016.64kBmap:436.62kBmaр: 6,283.55kBAPP...
|
NULL
|
|
47385
|
NULL
|
0
|
2026-04-17T11:34:56.552536+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425696552_m2.jpg...
|
Firefox
|
Dashboard · Jiminny · Membrane — Work
|
1
|
console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505 console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505?element=/connectors/64a158e7d2605720d232e07b...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Dashboard · Jiminny · Membrane
Dashboard · Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Workspace: Jiminny
Jiminny
Search
⌘K
Dashboard
Dashboard
Explore
Explore
Activity
Activity
Settings
Settings
Docs
Docs
Logout
Version
2026-04-16
Connectors
Connectors
Zoho CRM
Zoho CRM
Public
Development
Development
Test
Test
Overview
Overview
Connector Configuration
Connector Configuration
Operations
Operations
Data Collections
Data Collections
Universal Data Models
Universal Data Models
Global Webhooks
Global Webhooks
Events
Events
Editor content
34
36
37
45
46
makeApiClient
:
mapping
:
args
:
headers
:
Authorization
:
Agent
Agent
Beta
What would you like to do?...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"bounds":{"left":0.00234375,"top":0.045138888,"width":0.0890625,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"bounds":{"left":0.0,"top":0.08263889,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"bounds":{"left":0.015625,"top":0.09236111,"width":0.04453125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.11111111,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.12083333,"width":0.11445312,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.13958333,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"120216 is your HubSpot Log In Code - integration-account@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.015625,"top":0.14930555,"width":0.17734376,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"CloudWatch | eu-west-1","depth":4,"bounds":{"left":0.0,"top":0.16805555,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"CloudWatch | eu-west-1","depth":5,"bounds":{"left":0.015625,"top":0.17777778,"width":0.048828125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"New Tab","depth":4,"bounds":{"left":0.0,"top":0.19652778,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"New Tab","depth":5,"bounds":{"left":0.015625,"top":0.20625,"width":0.017578125,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":4,"bounds":{"left":0.0,"top":0.225,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Configure SSH access to multiple environment - Engineering - Confluence","depth":5,"bounds":{"left":0.015625,"top":0.23472223,"width":0.1515625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.2534722,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app","depth":5,"bounds":{"left":0.015625,"top":0.26319444,"width":0.17421874,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":4,"bounds":{"left":0.0,"top":0.28194445,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20692] Issue with reconnecting Zoho - Jira","depth":5,"bounds":{"left":0.015625,"top":0.29166666,"width":0.09726562,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.31041667,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015625,"top":0.3201389,"width":0.015625,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Auth Proxy","depth":4,"bounds":{"left":0.0,"top":0.33888888,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Auth Proxy","depth":5,"bounds":{"left":0.015625,"top":0.34861112,"width":0.021875,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Dashboard · Jiminny · Membrane","depth":4,"bounds":{"left":0.0,"top":0.3673611,"width":0.09375,"height":0.028472222},"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Dashboard · Jiminny · Membrane","depth":5,"bounds":{"left":0.015625,"top":0.37708333,"width":0.06679688,"height":0.009722223},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.07890625,"top":0.37361112,"width":0.009375,"height":0.016666668},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.003125,"top":0.39722222,"width":0.08710937,"height":0.022222223},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.003125,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.01640625,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.029296875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.0421875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.05546875,"top":0.97430557,"width":0.0125,"height":0.022222223},"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Workspace: Jiminny","depth":10,"bounds":{"left":0.09609375,"top":0.047916666,"width":0.0265625,"height":0.05277778},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":12,"bounds":{"left":0.09921875,"top":0.088194445,"width":0.01484375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search","depth":10,"bounds":{"left":0.09765625,"top":0.10625,"width":0.0234375,"height":0.023611112},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"⌘K","depth":11,"bounds":{"left":0.11054687,"top":0.11388889,"width":0.00546875,"height":0.008333334},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Dashboard","depth":11,"bounds":{"left":0.09609375,"top":0.13541667,"width":0.0265625,"height":0.038194444},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Dashboard","depth":12,"bounds":{"left":0.09921875,"top":0.15833333,"width":0.0203125,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Explore","depth":11,"bounds":{"left":0.09609375,"top":0.17638889,"width":0.0265625,"height":0.038194444},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Explore","depth":12,"bounds":{"left":0.10234375,"top":0.19930555,"width":0.0140625,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Activity","depth":11,"bounds":{"left":0.09609375,"top":0.21736111,"width":0.0265625,"height":0.038194444},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Activity","depth":12,"bounds":{"left":0.10195313,"top":0.24027778,"width":0.01484375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Settings","depth":11,"bounds":{"left":0.09609375,"top":0.25833333,"width":0.0265625,"height":0.038194444},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Settings","depth":12,"bounds":{"left":0.1015625,"top":0.28125,"width":0.015625,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Docs","depth":11,"bounds":{"left":0.09609375,"top":0.30833334,"width":0.0265625,"height":0.038194444},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Docs","depth":12,"bounds":{"left":0.10234375,"top":0.33125,"width":0.009375,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Logout","depth":10,"bounds":{"left":0.09609375,"top":0.9166667,"width":0.0265625,"height":0.038194444},"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Version","depth":11,"bounds":{"left":0.10234375,"top":0.9673611,"width":0.0140625,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"2026-04-16","depth":11,"bounds":{"left":0.0984375,"top":0.9791667,"width":0.021875,"height":0.009027778},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Connectors","depth":18,"bounds":{"left":0.13125,"top":0.054166667,"width":0.030078124,"height":0.0125},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Connectors","depth":19,"bounds":{"left":0.13125,"top":0.054166667,"width":0.030078124,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Zoho CRM","depth":18,"bounds":{"left":0.16914062,"top":0.054166667,"width":0.02734375,"height":0.0125},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Zoho CRM","depth":19,"bounds":{"left":0.16914062,"top":0.054166667,"width":0.02734375,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Public","depth":15,"bounds":{"left":0.21171875,"top":0.055555556,"width":0.013671875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXComboBox","text":"Development","depth":15,"bounds":{"left":0.23320313,"top":0.052083332,"width":0.056640625,"height":0.016666668},"value":"Development","help_text":"","role_description":"combo box","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Development","depth":17,"bounds":{"left":0.246875,"top":0.055555556,"width":0.029296875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Test","depth":15,"bounds":{"left":0.6304687,"top":0.050694443,"width":0.03203125,"height":0.019444445},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Test","depth":16,"bounds":{"left":0.6449219,"top":0.054166667,"width":0.0109375,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Overview","depth":20,"bounds":{"left":0.128125,"top":0.08194444,"width":0.07460938,"height":0.022916667},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Overview","depth":22,"bounds":{"left":0.1390625,"top":0.0875,"width":0.024609376,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Connector Configuration","depth":18,"bounds":{"left":0.128125,"top":0.11875,"width":0.07460938,"height":0.017361112},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Connector Configuration","depth":19,"bounds":{"left":0.1296875,"top":0.121527776,"width":0.06015625,"height":0.011805556},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Operations","depth":20,"bounds":{"left":0.128125,"top":0.1388889,"width":0.07460938,"height":0.022916667},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Operations","depth":22,"bounds":{"left":0.1390625,"top":0.14444445,"width":0.028515626,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Data Collections","depth":20,"bounds":{"left":0.128125,"top":0.16319445,"width":0.07460938,"height":0.022916667},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Data Collections","depth":22,"bounds":{"left":0.1390625,"top":0.16875,"width":0.0421875,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Universal Data Models","depth":20,"bounds":{"left":0.128125,"top":0.1875,"width":0.07460938,"height":0.022916667},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Universal Data Models","depth":22,"bounds":{"left":0.1390625,"top":0.19305556,"width":0.058203124,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Global Webhooks","depth":20,"bounds":{"left":0.128125,"top":0.21180555,"width":0.07460938,"height":0.022916667},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Global Webhooks","depth":22,"bounds":{"left":0.1390625,"top":0.21736111,"width":0.0453125,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Events","depth":20,"bounds":{"left":0.128125,"top":0.2361111,"width":0.07460938,"height":0.022916667},"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Events","depth":22,"bounds":{"left":0.1390625,"top":0.24166666,"width":0.0171875,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXTextArea","text":"Editor content","depth":20,"help_text":"","role_description":"editor","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"34","depth":23,"bounds":{"left":0.215625,"top":0.07777778,"width":0.00546875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"","depth":23,"bounds":{"left":0.22382812,"top":0.077083334,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"36","depth":23,"bounds":{"left":0.215625,"top":0.090277776,"width":0.00546875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"","depth":23,"bounds":{"left":0.22382812,"top":0.08958333,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"37","depth":23,"bounds":{"left":0.215625,"top":0.10277778,"width":0.00546875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"","depth":23,"bounds":{"left":0.22382812,"top":0.10208333,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"45","depth":23,"bounds":{"left":0.215625,"top":0.115277775,"width":0.00546875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"","depth":23,"bounds":{"left":0.22382812,"top":0.114583336,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"46","depth":23,"bounds":{"left":0.215625,"top":0.12777779,"width":0.00546875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"","depth":23,"bounds":{"left":0.22382812,"top":0.12708333,"width":0.00625,"height":0.011111111},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"makeApiClient","depth":24,"bounds":{"left":0.22734375,"top":0.07777778,"width":0.03671875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":24,"bounds":{"left":0.2640625,"top":0.07777778,"width":0.002734375,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mapping","depth":24,"bounds":{"left":0.2328125,"top":0.090277776,"width":0.019921875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":24,"bounds":{"left":0.25273436,"top":0.090277776,"width":0.002734375,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"args","depth":24,"bounds":{"left":0.23867187,"top":0.10277778,"width":0.011328125,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":24,"bounds":{"left":0.25,"top":0.10277778,"width":0.002734375,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"headers","depth":24,"bounds":{"left":0.24414062,"top":0.115277775,"width":0.019921875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":24,"bounds":{"left":0.2640625,"top":0.115277775,"width":0.002734375,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Authorization","depth":24,"bounds":{"left":0.25,"top":0.12777779,"width":0.03671875,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":24,"bounds":{"left":0.28671876,"top":0.12777779,"width":0.002734375,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Agent","depth":12,"bounds":{"left":0.70820314,"top":0.05347222,"width":0.016015625,"height":0.014583333},"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Agent","depth":13,"bounds":{"left":0.70820314,"top":0.054166667,"width":0.016015625,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Beta","depth":13,"bounds":{"left":0.98125,"top":0.055555556,"width":0.01015625,"height":0.010416667},"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXTextField","text":"","depth":13,"bounds":{"left":0.7046875,"top":0.09652778,"width":0.28515625,"height":0.022222223},"value":"","help_text":"","role_description":"text field","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"What would you like to do?","depth":14,"bounds":{"left":0.7046875,"top":0.09791667,"width":0.06992187,"height":0.0125},"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
5638205737690869664
|
-7333444280310396340
|
visual_change
|
accessibility
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
Inbox (1,576) - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
120216 is your HubSpot Log In Code - [EMAIL] - Jiminny Mail
CloudWatch | eu-west-1
CloudWatch | eu-west-1
New Tab
New Tab
Configure SSH access to multiple environment - Engineering - Confluence
Configure SSH access to multiple environment - Engineering - Confluence
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
fix-cache-for-business-processes by ilian-jiminny · Pull Request #11985 · jiminny/app
[JY-20692] Issue with reconnecting Zoho - Jira
[JY-20692] Issue with reconnecting Zoho - Jira
Jiminny
Jiminny
Auth Proxy
Auth Proxy
Dashboard · Jiminny · Membrane
Dashboard · Jiminny · Membrane
Close tab
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Workspace: Jiminny
Jiminny
Search
⌘K
Dashboard
Dashboard
Explore
Explore
Activity
Activity
Settings
Settings
Docs
Docs
Logout
Version
2026-04-16
Connectors
Connectors
Zoho CRM
Zoho CRM
Public
Development
Development
Test
Test
Overview
Overview
Connector Configuration
Connector Configuration
Operations
Operations
Data Collections
Data Collections
Universal Data Models
Universal Data Models
Global Webhooks
Global Webhooks
Events
Events
Editor content
34
36
37
45
46
makeApiClient
:
mapping
:
args
:
headers
:
Authorization
:
Agent
Agent
Beta
What would you like to do?...
|
47384
|
|
47386
|
1004
|
0
|
2026-04-17T11:35:20.775241+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425720775_m2.jpg...
|
Slack
|
Threads - Jiminny Inc - 2 new items - Slack
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Jiminny Inc
Jiminny (Staging)
Add workspaces
Home
Jiminny Inc
Jiminny (Staging)
Add workspaces
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
Directories
jiminny-x-integration-app
platform-inner-team
ai-chapter
alerts
backend
confusion-clinic
curiosity_lab
engineering
frontend
general
infra-changes
jiminny-bg
platform-tickets
product_launches
random
releases
support
thank-yous
the_people_of_jiminny
Nikolay Nikolov
Aneliya Angelova
,
Nikolay Yankov
,
Steliyan Georgiev
Galya Dimitrova
Stoyan Tanev
Vasil Vasilev
Nikolay Ivanov
Aneliya Angelova
Ves
Steliyan Georgiev
Jira Cloud
Toast
Google Calendar
jiminny-x-integration-app
jiminny-x-integration-app
Pylon and you
Lukas Kovalik
Yesterday at 11:04:11 AM
Yesterday at 11:04 AM
Hi guys, we have one issue we used to have before regarding the authorisation for Zoho CRM. When the clients go through all steps and login it just returns him back to the login screen. I believe this is the reference to the previous conversation
https://jiminny.slack.com/archives/C07RAC4U86M/p1748957897141919
https://jiminny.slack.com/archives/C07RAC4U86M/p1748957897141919
. Could you please have a look if there is any change?
Remove preview
Lukas Kovalik
Lukas Kovalik
There appears to be a recent change in the SDK OAuth mechanism. When a new client connects to the platform using Zoho, we no longer receive a Promise (
https://console.integration.app/ref/sdk/classes/IntegrationAccessor.html#openNewConnection
https://console.integration.app/ref/sdk/classes/IntegrationAccessor.html#openNewConnection
) upon successful login. This functionality was working just a few weeks ago.
(edited)
Thread in jiminny-x-integration-app
Thread in
jiminny-x-integration-app
|
Jun 3rd, 2025
Jun 3rd, 2025
|
View message
View message
Membrane AI Assistant
APP
Yesterday at 11:04:58 AM
Yesterday at 11:04 AM
Hi
Lukas
, thanks for reporting this. I'll help investigate the Zoho CRM authorization issue.
To help me debug this, could you please share:
The link to the affected Membrane workspace (from the browser URL bar, should look like
https://console.getmembrane.com/w/<workspace-id>
)
Which specific Zoho CRM connection is experiencing this issue (or a link to the connection if possible)
Lukas Kovalik
Yesterday at 11:07:56 AM
Yesterday at 11:07 AM
https://console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505/connections?tenantId=69df632cfa483f45adcf1a2b
https://console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505/connections?tenantId=69df632cfa483f45adcf1a2b
React with white_check_mark
React with eyes...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Jiminny Inc","depth":12,"bounds":{"left":0.00546875,"top":0.05486111,"width":0.0125,"height":0.022222223},"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXRadioButton","text":"Jiminny (Staging)","depth":12,"bounds":{"left":0.00546875,"top":0.09097222,"width":0.0125,"height":0.022222223},"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"Add workspaces","depth":12,"bounds":{"left":0.00546875,"top":0.12708333,"width":0.0125,"height":0.022222223},"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":14,"bounds":{"left":0.026953125,"top":0.048611112,"width":0.020703126,"height":0.047222223},"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":16,"bounds":{"left":0.03125,"top":0.08125,"width":0.012109375,"height":0.009027778},"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":14,"bounds":{"left":0.026953125,"top":0.09583333,"width":0.020703126,"height":0.047222223},"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":16,"bounds":{"left":0.032421876,"top":0.12847222,"width":0.009765625,"height":0.009027778},"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":14,"bounds":{"left":0.026953125,"top":0.14305556,"width":0.020703126,"height":0.047222223},"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":16,"bounds":{"left":0.0296875,"top":0.17569445,"width":0.015234375,"height":0.009027778},"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":14,"bounds":{"left":0.026953125,"top":0.19027779,"width":0.020703126,"height":0.047222223},"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":16,"bounds":{"left":0.0328125,"top":0.22291666,"width":0.008984375,"height":0.009027778},"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":14,"bounds":{"left":0.026953125,"top":0.2375,"width":0.020703126,"height":0.047222223},"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":16,"bounds":{"left":0.03203125,"top":0.2701389,"width":0.010546875,"height":0.009027778},"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":14,"bounds":{"left":0.026953125,"top":0.2847222,"width":0.020703126,"height":0.047222223},"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":16,"bounds":{"left":0.03203125,"top":0.31736112,"width":0.010546875,"height":0.009027778},"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":20,"bounds":{"left":0.06679688,"top":0.0875,"width":0.022265624,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":20,"bounds":{"left":0.06679688,"top":0.10694444,"width":0.020703126,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":20,"bounds":{"left":0.06679688,"top":0.12638889,"width":0.021484375,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":20,"bounds":{"left":0.06679688,"top":0.14583333,"width":0.034375,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":20,"bounds":{"left":0.06679688,"top":0.16527778,"width":0.028515626,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"jiminny-x-integration-app","depth":20,"bounds":{"left":0.07304688,"top":0.24722221,"width":0.0515625,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":20,"bounds":{"left":0.07304688,"top":0.26666668,"width":0.05234375,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":22,"bounds":{"left":0.07304688,"top":0.3125,"width":0.026171874,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":22,"bounds":{"left":0.07304688,"top":0.33194444,"width":0.014453125,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":22,"bounds":{"left":0.07304688,"top":0.3513889,"width":0.021484375,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":22,"bounds":{"left":0.07304688,"top":0.37083334,"width":0.040625,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"curiosity_lab","depth":22,"bounds":{"left":0.07304688,"top":0.39027777,"width":0.032421876,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":22,"bounds":{"left":0.07304688,"top":0.4097222,"width":0.03046875,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"frontend","depth":22,"bounds":{"left":0.07304688,"top":0.42916667,"width":0.02265625,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"general","depth":22,"bounds":{"left":0.07304688,"top":0.4486111,"width":0.019140625,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":22,"bounds":{"left":0.07304688,"top":0.46805555,"width":0.034765624,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":22,"bounds":{"left":0.07304688,"top":0.4875,"width":0.02734375,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":22,"bounds":{"left":0.07304688,"top":0.5069444,"width":0.041015625,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":22,"bounds":{"left":0.07304688,"top":0.5263889,"width":0.0453125,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"random","depth":22,"bounds":{"left":0.07304688,"top":0.54583335,"width":0.019921875,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":22,"bounds":{"left":0.07304688,"top":0.56527776,"width":0.020703126,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"support","depth":22,"bounds":{"left":0.07304688,"top":0.5847222,"width":0.0203125,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":22,"bounds":{"left":0.07304688,"top":0.6041667,"width":0.02890625,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":22,"bounds":{"left":0.07304688,"top":0.6236111,"width":0.053125,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Nikolov","depth":22,"bounds":{"left":0.07304688,"top":0.66944444,"width":0.040234376,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Aneliya Angelova","depth":22,"bounds":{"left":0.07304688,"top":0.6888889,"width":0.044140626,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":",","depth":22,"bounds":{"left":0.11679687,"top":0.6888889,"width":0.0078125,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":22,"bounds":{"left":0.11992188,"top":0.6888889,"width":0.016796876,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":",","depth":22,"bounds":{"left":0.13632813,"top":0.70416665,"width":0.000390625,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":22,"bounds":{"left":0.13632813,"top":0.70416665,"width":0.000390625,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":22,"bounds":{"left":0.07304688,"top":0.7083333,"width":0.04140625,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tanev","depth":22,"bounds":{"left":0.07304688,"top":0.7277778,"width":0.033984374,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":22,"bounds":{"left":0.07304688,"top":0.74722224,"width":0.03125,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Ivanov","depth":22,"bounds":{"left":0.07304688,"top":0.76666665,"width":0.037890624,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Aneliya Angelova","depth":22,"bounds":{"left":0.07304688,"top":0.7861111,"width":0.044140626,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":22,"bounds":{"left":0.07304688,"top":0.8055556,"width":0.009375,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":22,"bounds":{"left":0.07304688,"top":0.825,"width":0.044921875,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":20,"bounds":{"left":0.07304688,"top":0.87083334,"width":0.026171874,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":20,"bounds":{"left":0.07304688,"top":0.8902778,"width":0.014453125,"height":0.0125},"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":20,"bounds":{"left":0.07304688,"top":0.9097222,"width":0.0359375,"height":0.0125},"role_description":"text"},{"role":"AXLink","text":"jiminny-x-integration-app","depth":21,"bounds":{"left":0.14765625,"top":0.07986111,"width":0.0734375,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"jiminny-x-integration-app","depth":22,"bounds":{"left":0.15429688,"top":0.07986111,"width":0.06679688,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"Pylon and you","depth":21,"bounds":{"left":0.14804688,"top":0.07986111,"width":0.029296875,"height":0.00069444446},"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":23,"bounds":{"left":0.16875,"top":0.07986111,"width":0.036328126,"height":0.00069444446},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":23,"bounds":{"left":0.2046875,"top":0.07986111,"width":0.003515625,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"Yesterday at 11:04:11 AM","depth":23,"bounds":{"left":0.2078125,"top":0.07986111,"width":0.047265626,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Yesterday at 11:04 AM","depth":24,"bounds":{"left":0.2078125,"top":0.07986111,"width":0.047265626,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"Hi guys, we have one issue we used to have before regarding the authorisation for Zoho CRM. When the clients go through all steps and login it just returns him back to the login screen. I believe this is the reference to the previous conversation","depth":24,"bounds":{"left":0.16875,"top":0.07986111,"width":0.315625,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"https://jiminny.slack.com/archives/C07RAC4U86M/p1748957897141919","depth":24,"bounds":{"left":0.16875,"top":0.07986111,"width":0.19140625,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://jiminny.slack.com/archives/C07RAC4U86M/p1748957897141919","depth":25,"bounds":{"left":0.16875,"top":0.07986111,"width":0.19140625,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":". Could you please have a look if there is any change?","depth":24,"bounds":{"left":0.16875,"top":0.07986111,"width":0.3046875,"height":0.00069444446},"role_description":"text"},{"role":"AXButton","text":"Remove preview","depth":25,"bounds":{"left":0.1609375,"top":0.07986111,"width":0.0078125,"height":0.00069444446},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":25,"bounds":{"left":0.184375,"top":0.07986111,"width":0.037109375,"height":0.00069444446},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Lukas Kovalik","depth":27,"bounds":{"left":0.184375,"top":0.07986111,"width":0.035546876,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"There appears to be a recent change in the SDK OAuth mechanism. When a new client connects to the platform using Zoho, we no longer receive a Promise (","depth":26,"bounds":{"left":0.1859375,"top":0.07986111,"width":0.20703125,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"https://console.integration.app/ref/sdk/classes/IntegrationAccessor.html#openNewConnection","depth":26,"bounds":{"left":0.1859375,"top":0.07986111,"width":0.2109375,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://console.integration.app/ref/sdk/classes/IntegrationAccessor.html#openNewConnection","depth":27,"bounds":{"left":0.1859375,"top":0.07986111,"width":0.2109375,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":") upon successful login. This functionality was working just a few weeks ago.","depth":26,"bounds":{"left":0.1859375,"top":0.07986111,"width":0.19921875,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":25,"bounds":{"left":0.175,"top":0.07986111,"width":0.016796876,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"Thread in jiminny-x-integration-app","depth":25,"bounds":{"left":0.175,"top":0.07986111,"width":0.07851563,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Thread in","depth":26,"bounds":{"left":0.175,"top":0.07986111,"width":0.020703126,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"jiminny-x-integration-app","depth":26,"bounds":{"left":0.20078126,"top":0.07986111,"width":0.052734375,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"|","depth":25,"bounds":{"left":0.253125,"top":0.07986111,"width":0.00390625,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"Jun 3rd, 2025","depth":25,"bounds":{"left":0.2566406,"top":0.07986111,"width":0.028515626,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Jun 3rd, 2025","depth":26,"bounds":{"left":0.2566406,"top":0.07986111,"width":0.028515626,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"|","depth":25,"bounds":{"left":0.28476563,"top":0.07986111,"width":0.00390625,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"View message","depth":25,"bounds":{"left":0.28828126,"top":0.07986111,"width":0.0296875,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"View message","depth":26,"bounds":{"left":0.28828126,"top":0.07986111,"width":0.0296875,"height":0.00069444446},"role_description":"text"},{"role":"AXButton","text":"Membrane AI Assistant","depth":23,"bounds":{"left":0.16875,"top":0.07986111,"width":0.06171875,"height":0.00069444446},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"APP","depth":23,"bounds":{"left":0.2328125,"top":0.07986111,"width":0.0078125,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"","depth":23,"bounds":{"left":0.24140625,"top":0.07986111,"width":0.003515625,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"Yesterday at 11:04:58 AM","depth":23,"bounds":{"left":0.24453124,"top":0.07986111,"width":0.047265626,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Yesterday at 11:04 AM","depth":24,"bounds":{"left":0.24453124,"top":0.07986111,"width":0.047265626,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"Hi","depth":23,"bounds":{"left":0.16875,"top":0.07986111,"width":0.007421875,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"Lukas","depth":23,"bounds":{"left":0.17578125,"top":0.07986111,"width":0.01484375,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":", thanks for reporting this. I'll help investigate the Zoho CRM authorization issue.","depth":23,"bounds":{"left":0.190625,"top":0.07986111,"width":0.20585938,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"To help me debug this, could you please share:","depth":23,"bounds":{"left":0.16875,"top":0.07986111,"width":0.11875,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"","depth":26,"bounds":{"left":0.16992188,"top":0.07986111,"width":0.00625,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"The link to the affected Membrane workspace (from the browser URL bar, should look like","depth":25,"bounds":{"left":0.1796875,"top":0.07986111,"width":0.23007813,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"https://console.getmembrane.com/w/<workspace-id>","depth":26,"bounds":{"left":0.18125,"top":0.07986111,"width":0.13515624,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":")","depth":25,"bounds":{"left":0.31757814,"top":0.07986111,"width":0.001953125,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"","depth":26,"bounds":{"left":0.16992188,"top":0.07986111,"width":0.00625,"height":0.00069444446},"role_description":"text"},{"role":"AXStaticText","text":"Which specific Zoho CRM connection is experiencing this issue (or a link to the connection if possible)","depth":25,"bounds":{"left":0.1796875,"top":0.07986111,"width":0.2609375,"height":0.00069444446},"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":23,"bounds":{"left":0.16875,"top":0.07986111,"width":0.036328126,"height":0.00069444446},"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":23,"bounds":{"left":0.2046875,"top":0.07986111,"width":0.003515625,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"Yesterday at 11:07:56 AM","depth":23,"bounds":{"left":0.2078125,"top":0.07986111,"width":0.047265626,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Yesterday at 11:07 AM","depth":24,"bounds":{"left":0.2078125,"top":0.07986111,"width":0.047265626,"height":0.00069444446},"role_description":"text"},{"role":"AXLink","text":"https://console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505/connections?tenantId=69df632cfa483f45adcf1a2b","depth":24,"bounds":{"left":0.16875,"top":0.07986111,"width":0.30742186,"height":0.00069444446},"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505/connections?tenantId=69df632cfa483f45adcf1a2b","depth":25,"bounds":{"left":0.16875,"top":0.07986111,"width":0.30742186,"height":0.00069444446},"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":25,"bounds":{"left":0.39570314,"top":0.07986111,"width":0.0125,"height":0.00069444446},"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":25,"bounds":{"left":0.40820312,"top":0.07986111,"width":0.0125,"height":0.00069444446},"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
582864970981691915
|
-1765974734009488311
|
visual_change
|
hybrid
|
NULL
|
Jiminny Inc
Jiminny (Staging)
Add workspaces
Home
Jiminny Inc
Jiminny (Staging)
Add workspaces
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
Directories
jiminny-x-integration-app
platform-inner-team
ai-chapter
alerts
backend
confusion-clinic
curiosity_lab
engineering
frontend
general
infra-changes
jiminny-bg
platform-tickets
product_launches
random
releases
support
thank-yous
the_people_of_jiminny
Nikolay Nikolov
Aneliya Angelova
,
Nikolay Yankov
,
Steliyan Georgiev
Galya Dimitrova
Stoyan Tanev
Vasil Vasilev
Nikolay Ivanov
Aneliya Angelova
Ves
Steliyan Georgiev
Jira Cloud
Toast
Google Calendar
jiminny-x-integration-app
jiminny-x-integration-app
Pylon and you
Lukas Kovalik
Yesterday at 11:04:11 AM
Yesterday at 11:04 AM
Hi guys, we have one issue we used to have before regarding the authorisation for Zoho CRM. When the clients go through all steps and login it just returns him back to the login screen. I believe this is the reference to the previous conversation
https://jiminny.slack.com/archives/C07RAC4U86M/p1748957897141919
https://jiminny.slack.com/archives/C07RAC4U86M/p1748957897141919
. Could you please have a look if there is any change?
Remove preview
Lukas Kovalik
Lukas Kovalik
There appears to be a recent change in the SDK OAuth mechanism. When a new client connects to the platform using Zoho, we no longer receive a Promise (
https://console.integration.app/ref/sdk/classes/IntegrationAccessor.html#openNewConnection
https://console.integration.app/ref/sdk/classes/IntegrationAccessor.html#openNewConnection
) upon successful login. This functionality was working just a few weeks ago.
(edited)
Thread in jiminny-x-integration-app
Thread in
jiminny-x-integration-app
|
Jun 3rd, 2025
Jun 3rd, 2025
|
View message
View message
Membrane AI Assistant
APP
Yesterday at 11:04:58 AM
Yesterday at 11:04 AM
Hi
Lukas
, thanks for reporting this. I'll help investigate the Zoho CRM authorization issue.
To help me debug this, could you please share:
The link to the affected Membrane workspace (from the browser URL bar, should look like
https://console.getmembrane.com/w/<workspace-id>
)
Which specific Zoho CRM connection is experiencing this issue (or a link to the connection if possible)
Lukas Kovalik
Yesterday at 11:07:56 AM
Yesterday at 11:07 AM
https://console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505/connections?tenantId=69df632cfa483f45adcf1a2b
https://console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505/connections?tenantId=69df632cfa483f45adcf1a2b
React with white_check_mark
React with eyes
SlackFileEditViewJiminny ...DMs= Unreads@ Threads6 Huddles* Drafts & sent8 DirectoriesAchivityEh External connectionsFiles# Starred& jiminny-x-integrati...A platform-inner-teamMorechannes# ai-chapter# alerts# backend# contusion-clinic# curiosity lab# engineering# frontend# general# infra-changes# jiminny-bg# platform-tickets# product_launchesac random# releases# support# thank-yous# the_people_of jimi...•- Direct messagesO. Nikolay Nikolov Q(3 Aneliya Angelova, ...®. Galya Dimitrova8. Stoyan TanevC. Vasil VasilevNikolay Ivanov®. Aneliya Angelovae VesR. Steliyan Georgiev# Apps# Jira CloudToastGoogle Cale…..HistoryWindowHelpQ Search Jiminny IncThreadsupgraded the connector? We don't want to show Connect via Membrane.3 fles& Download allC< 40 ll • f SupportDaily • in 25m.AUl CodeD Test100% ( Fri 17 Apr 14:35:20beld@ AgentWhat would you like to do?Linkina vour Zoho CRM accounti%dhah20Membrane Al Assistant APP Today at 1:17 PMThanks for the follow-up! Let me address both of your questions:1. Missing (disconnected| field in API responseYou're right to point this out. Looking at your API response, I can see it only has |connected | and not |di sconnected . Let meescalate this back to the engineering team to clarify which endpoints include both fields and which ones only haveconnected . This may differ between endpoints.2. Hiding "Connect via Membrane" optionThe "Connect via Membrane" (Auth Proxy) option appeared when you upgraded to connector v3.0.3. If you want to hide thisoption and only show "OAuth 2.0" to your users, you can disable the auth-proxy option in your integration settings.Let me get back to you shortly on the disconnected field question.Membrane Al Assistant APP 32 minutes agoI've investigated the code and found the issue! You're absolutely right - the disconnected field is missing from the GET/integrations/:key endpoint response.What's happening:The backward compatibility logic that adds disconnected = ! connegfed is only applied when you call GET/connections/:id directly. When the connection is nested in the integration response (from (GET /integrations/zohocrm),it bypasses this logic and only returns connected.Workaround for now:Instead of getting the connection from GET /integrations/zohocrm, you can:• Use [GET /connections/:connectionId directly - this endpoint includes both (connected and disconnected fields• Or. compute it vourself: disconnected = !connectedHiding "Connect via Membrane":To disable the auth-proxy option in your Zoho CRM integration settings, you can configure which auth options to show inyour integration settings in the Console.I'm escalating the missing |disconnected field issue to the engineering team to fix it across all endpoints. Would eitherworkaround work for you in the meantime?10 external people are from MembraneReply._ Also send to e jiminny-x-integration-appYou're up to dates encineerinelan кyuслuкov ana vellian Kyuchukov Today at 10:28 AMWe have a broken loop of syncing Stage changes for two clients, which results in non-stop requests to Prophet (which costs...
|
NULL
|
|
47388
|
1003
|
0
|
2026-04-17T11:35:21.873606+00:00
|
/Users/lukas/.screenpipe/data/data/2026-04-17/1776 /Users/lukas/.screenpipe/data/data/2026-04-17/1776425721873_m1.jpg...
|
Firefox
|
Dashboard · Jiminny · Membrane — Work
|
1
|
console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505 console.getmembrane.com/w/66fd5a6e813fde5d1b8aa505?element=/connectors/64a158e7d2605720d232e07b...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Workers | Datadog","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Developers | HubSpot","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Developers | HubSpot","depth":5,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,576) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
8673252839249871389
|
-5983303614938859068
|
click
|
hybrid
|
NULL
|
Workers | Datadog
Developers | HubSpot
Developers Workers | Datadog
Developers | HubSpot
Developers | HubSpot
Inbox (1,576) - [EMAIL] - Jiminny Mail
FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpla6]Support Daily - in 25 mA100% <47APP (-zsh)X4-zshDOCKER• ₴1DEV (docker)• *2APP (-zsh)X3-zsh./public/vue-assets/assets/ondemand-DutwAJ6x.js:./public/vue-assets/assets/CrmLink-DKYsnHnx.js./public/vue-assets/assets/liquor-tree-COUefof4.js./public/vue-assets/assets/DealRiskList-CjPoT6NF.js:./public/vue-assets/assets/AskAnything-a4BpUaF5.js:./public/vue-assets/assets/lib-CwM9toD2.js./public/vue-assets/assets/AppFormField-CtfldUq7.js:./public/vue-assets/assets/deal-view-DhouIWLw.js../public/vue-assets/assets/exports-D1lmea40.js../public/vue-assets/assets/playlists-BWns-By9.js../public/vue-assets/assets/callScoringTemplates-zeRn40ul.js../public/vue-assets/assets/_copy0bject-USkOnlaQ.js../public/vue-assets/assets/pusher-znYCfz7U.js./public/vue-assets/assets/onboard-BENebgvU.js./public/vue-assets/assets/StatusBadge-CmcY3nfX.js./public/vue-assets/assets/kiosk-1vhk4_89.js./public/vue-assets/assets/preload-helper-DCvhahzG.js../public/vue-assets/assets/deal-insights-DN-kVyxK.js../public/vue-assets/assets/ListView-POU6dSu7.js:./public/vue-assets/assets/_plugin-vue_export-helper-DD3s5456.js./public/vue-assets/assets/WelcomeLayout-B6wd32HG.js../public/vue-assets/assets/dashboard-DYH5MiIH.js:./public/vue-assets/assets/emoji-input-CSq87OVy.js../public/vue-assets/assets/AppButton-D3qMd0Dr.js../public/vue-assets/assets/sentry-c0Rhilsu.js:./public/vue-assets/assets/OrgSettingsLayout-ByQjX4wG.js./public/vue-assets/assets/vuex.esm-bundler-DqfufJ2-.js./public/vue-assets/assets/playback-BH9MB7YC.js./public/vue-assets/assets/index.module-Bjlhgfdl.js./public/vue-assets/assets/intl-tel-input-BW4mv40Q.js./public/vue-assets/assets/team-insights-BqCZQtVc.js../public/vue-assets/assets/popper-CQwVcrX4.js../public/vue-assets/assets/PhoneField-CwCIoAYm.js./public/vue-assets/assets/live-XL9ZmWsU.js./public/vue-assets/assets/video-js-skin.less_vue_type_style_index_0_src_true_lang-BN0485xV.js../public/vue-assets/assets/index-CPycMtZF.js../public/vue-assets/assets/logged-in-layout-B_JDhk5y.js• ₴526.88kB27.91kB30.75kB34.39kB39.50kB39.69kB41.91kB43.22kB47.84kB48.28kB55.13kB61.28kB62.98kB63.26kB64.66kB79.60kB82.59kB94.84kB115.71kB117.59 kВ120.67kB128.71 kB129.28 kB133.44 kB164.28kB176.33kB180.40kB198.79kB218.14kB264.94 kВ298.57kB307.13kB343.99kB367.43 kB689.63kB825.23 kB1,402.70 kB• built in 28.48s[plugin builtin:vite-reporter](!) Some chunksare larger than 500 kB after minification. Consider:- Using dynamic import() to code-split the application- Use build.rolldown0ptions.output.codeSplitting to improve chunking: [URL_WITH_CREDENTIALS] 88APP...
|
47382
|