@indexnetwork/protocol 6.6.2-rc.388.1 → 6.6.4-rc.390.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/dist/negotiation/negotiation.graph.d.ts +8 -2
- package/dist/negotiation/negotiation.graph.d.ts.map +1 -1
- package/dist/negotiation/negotiation.graph.js +19 -4
- package/dist/negotiation/negotiation.graph.js.map +1 -1
- package/dist/negotiation/negotiation.state.d.ts +5 -3
- package/dist/negotiation/negotiation.state.d.ts.map +1 -1
- package/dist/negotiation/negotiation.state.js +5 -1
- package/dist/negotiation/negotiation.state.js.map +1 -1
- package/dist/opportunity/opportunity.enricher.d.ts +5 -0
- package/dist/opportunity/opportunity.enricher.d.ts.map +1 -1
- package/dist/opportunity/opportunity.enricher.js +17 -1
- package/dist/opportunity/opportunity.enricher.js.map +1 -1
- package/dist/opportunity/opportunity.graph.d.ts +109 -247
- package/dist/opportunity/opportunity.graph.d.ts.map +1 -1
- package/dist/opportunity/opportunity.graph.js +199 -4
- package/dist/opportunity/opportunity.graph.js.map +1 -1
- package/dist/opportunity/opportunity.persist.d.ts +14 -1
- package/dist/opportunity/opportunity.persist.d.ts.map +1 -1
- package/dist/opportunity/opportunity.persist.js +33 -4
- package/dist/opportunity/opportunity.persist.js.map +1 -1
- package/dist/opportunity/opportunity.state.d.ts +17 -0
- package/dist/opportunity/opportunity.state.d.ts.map +1 -1
- package/dist/opportunity/opportunity.state.js +5 -0
- package/dist/opportunity/opportunity.state.js.map +1 -1
- package/dist/shared/interfaces/database.interface.d.ts +29 -5
- package/dist/shared/interfaces/database.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/database.interface.js.map +1 -1
- package/package.json +1 -1
|
@@ -71,6 +71,14 @@ function isActiveNegotiationTaskFresh(task) {
|
|
|
71
71
|
: 5 * 60 * 1000;
|
|
72
72
|
return Date.now() - new Date(task.updatedAt).getTime() < freshnessMs;
|
|
73
73
|
}
|
|
74
|
+
function triggerForOwner(opportunity, ownerUserId) {
|
|
75
|
+
return opportunity.detection.triggeredBy
|
|
76
|
+
?? opportunity.actors.find((actor) => actor.userId === ownerUserId)?.intent;
|
|
77
|
+
}
|
|
78
|
+
function belongsToOwnedIntent(opportunity, ownerUserId, triggerIntentId) {
|
|
79
|
+
return opportunity.detection.triggeredBy === triggerIntentId
|
|
80
|
+
|| opportunity.actors.some((actor) => actor.userId === ownerUserId && actor.intent === triggerIntentId);
|
|
81
|
+
}
|
|
74
82
|
/** Put an opportunity actor's exact intent first, then fill the bounded context without duplicates. */
|
|
75
83
|
export function buildPrioritizedNegotiationIntents(activeIntents, exactIntentId, fallbackIntent) {
|
|
76
84
|
const exactId = typeof exactIntentId === 'string' && exactIntentId.trim().length > 0
|
|
@@ -1946,6 +1954,7 @@ export class OpportunityGraphFactory {
|
|
|
1946
1954
|
return {
|
|
1947
1955
|
userId,
|
|
1948
1956
|
opportunityId: opp.id,
|
|
1957
|
+
opportunityStatus: opp.status,
|
|
1949
1958
|
opportunityUpdatedAt: opp.updatedAt,
|
|
1950
1959
|
reasoning: opp.interpretation?.reasoning ?? '',
|
|
1951
1960
|
valencyRole: candidateActor.role ?? 'peer',
|
|
@@ -2503,8 +2512,22 @@ export class OpportunityGraphFactory {
|
|
|
2503
2512
|
initialStatus,
|
|
2504
2513
|
});
|
|
2505
2514
|
if (state.evaluatedOpportunities.length === 0) {
|
|
2506
|
-
persistLog.verbose('No opportunities to persist'
|
|
2507
|
-
|
|
2515
|
+
persistLog.verbose('No opportunities to persist', {
|
|
2516
|
+
triggerIntentId: state.triggerIntentId,
|
|
2517
|
+
reason: state.candidates.length === 0 ? 'no_search_candidates' : 'evaluator_rejected_all',
|
|
2518
|
+
});
|
|
2519
|
+
return {
|
|
2520
|
+
opportunities: [],
|
|
2521
|
+
persistenceOutcome: {
|
|
2522
|
+
evaluatedCount: 0,
|
|
2523
|
+
createdCount: 0,
|
|
2524
|
+
reactivatedCount: 0,
|
|
2525
|
+
sameTriggerDuplicateSuppressions: 0,
|
|
2526
|
+
pairActiveNegotiationSuppressions: 0,
|
|
2527
|
+
crossTriggerAllowedCount: 0,
|
|
2528
|
+
finalAtomicConflictCount: 0,
|
|
2529
|
+
},
|
|
2530
|
+
};
|
|
2508
2531
|
}
|
|
2509
2532
|
try {
|
|
2510
2533
|
// Recompute the authoritative owner-side scope at the final boundary.
|
|
@@ -2580,6 +2603,7 @@ export class OpportunityGraphFactory {
|
|
|
2580
2603
|
};
|
|
2581
2604
|
const itemsToPersist = [];
|
|
2582
2605
|
const reactivatedOpportunities = [];
|
|
2606
|
+
let crossTriggerAllowedCount = 0;
|
|
2583
2607
|
const existingBetweenActors = [];
|
|
2584
2608
|
const now = new Date().toISOString();
|
|
2585
2609
|
// Only skip 'draft' (chat-only) opportunities during dedup.
|
|
@@ -2883,7 +2907,137 @@ export class OpportunityGraphFactory {
|
|
|
2883
2907
|
count: overlapping.length,
|
|
2884
2908
|
results: overlapping.map(o => ({ id: o.id, status: o.status, actors: o.actors?.map((a) => ({ userId: a.userId, role: a.role })) })),
|
|
2885
2909
|
});
|
|
2886
|
-
|
|
2910
|
+
const ownedIntentTriggerId = state.discoverySource === 'intent'
|
|
2911
|
+
&& state.triggerIntentId
|
|
2912
|
+
&& state.resolvedTriggerIntentId === state.triggerIntentId
|
|
2913
|
+
? state.triggerIntentId
|
|
2914
|
+
: undefined;
|
|
2915
|
+
if (ownedIntentTriggerId && candidateUserId) {
|
|
2916
|
+
let activeNegotiation;
|
|
2917
|
+
for (const opportunity of overlapping) {
|
|
2918
|
+
if (opportunity.status !== 'negotiating')
|
|
2919
|
+
continue;
|
|
2920
|
+
const task = await this.database.getNegotiationTaskForOpportunity(opportunity.id);
|
|
2921
|
+
if (task && isActiveNegotiationTaskFresh(task)) {
|
|
2922
|
+
activeNegotiation = { opportunity, taskState: task.state };
|
|
2923
|
+
break;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
if (activeNegotiation) {
|
|
2927
|
+
const existingTriggerIntentId = triggerForOwner(activeNegotiation.opportunity, state.userId);
|
|
2928
|
+
existingBetweenActors.push({
|
|
2929
|
+
candidateUserId: candidateUserId,
|
|
2930
|
+
networkId: (activeNegotiation.opportunity.context?.networkId ?? state.networkId ?? state.userNetworks?.[0] ?? ''),
|
|
2931
|
+
existingOpportunityId: activeNegotiation.opportunity.id,
|
|
2932
|
+
existingStatus: activeNegotiation.opportunity.status,
|
|
2933
|
+
reason: 'pair_active_negotiation',
|
|
2934
|
+
...(existingTriggerIntentId ? { existingTriggerIntentId } : {}),
|
|
2935
|
+
});
|
|
2936
|
+
persistDedupLog.info('Suppressing owned-intent match for pair-global active negotiation', {
|
|
2937
|
+
triggerIntentId: ownedIntentTriggerId,
|
|
2938
|
+
candidateUserId,
|
|
2939
|
+
existingOpportunityId: activeNegotiation.opportunity.id,
|
|
2940
|
+
existingTriggerIntentId,
|
|
2941
|
+
existingStatus: activeNegotiation.opportunity.status,
|
|
2942
|
+
existingAgeMs: Date.now() - new Date(activeNegotiation.opportunity.createdAt).getTime(),
|
|
2943
|
+
taskState: activeNegotiation.taskState,
|
|
2944
|
+
reason: 'pair_active_negotiation',
|
|
2945
|
+
});
|
|
2946
|
+
continue;
|
|
2947
|
+
}
|
|
2948
|
+
const sameTrigger = overlapping
|
|
2949
|
+
.filter((opportunity) => belongsToOwnedIntent(opportunity, state.userId, ownedIntentTriggerId))
|
|
2950
|
+
.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
2951
|
+
const otherTrigger = overlapping.filter((opportunity) => !belongsToOwnedIntent(opportunity, state.userId, ownedIntentTriggerId));
|
|
2952
|
+
const existing = sameTrigger[0];
|
|
2953
|
+
if (!existing) {
|
|
2954
|
+
if (otherTrigger.length > 0) {
|
|
2955
|
+
crossTriggerAllowedCount += 1;
|
|
2956
|
+
persistDedupLog.info('Allowing cross-trigger match for owned intent', {
|
|
2957
|
+
triggerIntentId: ownedIntentTriggerId,
|
|
2958
|
+
candidateUserId,
|
|
2959
|
+
reason: 'cross_trigger_match_allowed',
|
|
2960
|
+
otherTriggers: otherTrigger.map((opportunity) => ({
|
|
2961
|
+
opportunityId: opportunity.id,
|
|
2962
|
+
triggerIntentId: triggerForOwner(opportunity, state.userId),
|
|
2963
|
+
status: opportunity.status,
|
|
2964
|
+
ageMs: Date.now() - new Date(opportunity.createdAt).getTime(),
|
|
2965
|
+
})),
|
|
2966
|
+
});
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
else {
|
|
2970
|
+
const existingIndexId = (existing.context?.networkId ?? state.networkId ?? state.userNetworks?.[0] ?? '');
|
|
2971
|
+
const isRecent = new Date(existing.createdAt).getTime() > Date.now() - DEDUP_WINDOW_MS;
|
|
2972
|
+
if (existing.status === 'expired' || existing.status === 'stalled') {
|
|
2973
|
+
const reactivated = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
|
|
2974
|
+
if (reactivated) {
|
|
2975
|
+
persistLog.info('Reactivated same-trigger opportunity', {
|
|
2976
|
+
triggerIntentId: ownedIntentTriggerId,
|
|
2977
|
+
opportunityId: existing.id,
|
|
2978
|
+
candidateUserId,
|
|
2979
|
+
previousStatus: existing.status,
|
|
2980
|
+
newStatus: initialStatus,
|
|
2981
|
+
});
|
|
2982
|
+
reactivatedOpportunities.push(reactivated);
|
|
2983
|
+
}
|
|
2984
|
+
continue;
|
|
2985
|
+
}
|
|
2986
|
+
if (existing.status === 'negotiating') {
|
|
2987
|
+
const reactivated = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
|
|
2988
|
+
if (reactivated) {
|
|
2989
|
+
persistLog.info('Resuming same-trigger orphaned negotiating opportunity', {
|
|
2990
|
+
triggerIntentId: ownedIntentTriggerId,
|
|
2991
|
+
opportunityId: existing.id,
|
|
2992
|
+
candidateUserId,
|
|
2993
|
+
});
|
|
2994
|
+
reactivatedOpportunities.push(reactivated);
|
|
2995
|
+
}
|
|
2996
|
+
continue;
|
|
2997
|
+
}
|
|
2998
|
+
if (existing.status === 'latent' && initialStatus !== 'latent') {
|
|
2999
|
+
const upgraded = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
|
|
3000
|
+
if (upgraded) {
|
|
3001
|
+
persistLog.info('Upgraded same-trigger latent opportunity', {
|
|
3002
|
+
triggerIntentId: ownedIntentTriggerId,
|
|
3003
|
+
opportunityId: existing.id,
|
|
3004
|
+
candidateUserId,
|
|
3005
|
+
newStatus: initialStatus,
|
|
3006
|
+
});
|
|
3007
|
+
reactivatedOpportunities.push(upgraded);
|
|
3008
|
+
}
|
|
3009
|
+
continue;
|
|
3010
|
+
}
|
|
3011
|
+
if (isRecent) {
|
|
3012
|
+
existingBetweenActors.push({
|
|
3013
|
+
candidateUserId: candidateUserId,
|
|
3014
|
+
networkId: existingIndexId,
|
|
3015
|
+
existingOpportunityId: existing.id,
|
|
3016
|
+
existingStatus: existing.status,
|
|
3017
|
+
reason: 'same_trigger_recent_duplicate',
|
|
3018
|
+
existingTriggerIntentId: ownedIntentTriggerId,
|
|
3019
|
+
});
|
|
3020
|
+
persistDedupLog.info('Suppressing recent same-trigger duplicate', {
|
|
3021
|
+
triggerIntentId: ownedIntentTriggerId,
|
|
3022
|
+
candidateUserId,
|
|
3023
|
+
existingOpportunityId: existing.id,
|
|
3024
|
+
existingTriggerIntentId: ownedIntentTriggerId,
|
|
3025
|
+
existingStatus: existing.status,
|
|
3026
|
+
existingAgeMs: Date.now() - new Date(existing.createdAt).getTime(),
|
|
3027
|
+
reason: 'same_trigger_recent_duplicate',
|
|
3028
|
+
});
|
|
3029
|
+
continue;
|
|
3030
|
+
}
|
|
3031
|
+
persistDedupLog.info('Allowing same-trigger opportunity outside dedup window', {
|
|
3032
|
+
triggerIntentId: ownedIntentTriggerId,
|
|
3033
|
+
candidateUserId,
|
|
3034
|
+
existingOpportunityId: existing.id,
|
|
3035
|
+
existingStatus: existing.status,
|
|
3036
|
+
existingAgeMs: Date.now() - new Date(existing.createdAt).getTime(),
|
|
3037
|
+
});
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
else if (overlapping.length > 0) {
|
|
2887
3041
|
const existing = overlapping[0];
|
|
2888
3042
|
const existingIndexId = (existing.context?.networkId ?? state.networkId ?? state.userNetworks?.[0] ?? '');
|
|
2889
3043
|
const isRecent = new Date(existing.createdAt).getTime() > Date.now() - DEDUP_WINDOW_MS;
|
|
@@ -3076,12 +3230,42 @@ export class OpportunityGraphFactory {
|
|
|
3076
3230
|
}
|
|
3077
3231
|
}
|
|
3078
3232
|
}
|
|
3079
|
-
const
|
|
3233
|
+
const intentDedupScope = finalTriggerIntentId && state.discoverySource === 'intent'
|
|
3234
|
+
? { triggerIntentId: finalTriggerIntentId, dedupWindowMs: DEDUP_WINDOW_MS }
|
|
3235
|
+
: undefined;
|
|
3236
|
+
const { created: createdList, conflicts } = await persistOpportunities({
|
|
3080
3237
|
database: this.database,
|
|
3081
3238
|
embedder: this.embedder,
|
|
3082
3239
|
items: itemsForPersistence,
|
|
3083
3240
|
networkEligibility,
|
|
3241
|
+
intentDedupScope,
|
|
3084
3242
|
});
|
|
3243
|
+
for (const conflict of conflicts) {
|
|
3244
|
+
const item = itemsForPersistence[conflict.itemIndex];
|
|
3245
|
+
const candidateActor = item?.actors.find((actor) => actor.userId !== state.userId);
|
|
3246
|
+
if (!candidateActor)
|
|
3247
|
+
continue;
|
|
3248
|
+
existingBetweenActors.push({
|
|
3249
|
+
candidateUserId: candidateActor.userId,
|
|
3250
|
+
networkId: candidateActor.networkId,
|
|
3251
|
+
existingOpportunityId: conflict.existingOpportunityId,
|
|
3252
|
+
existingStatus: conflict.existingStatus,
|
|
3253
|
+
reason: conflict.reason,
|
|
3254
|
+
...(conflict.existingTriggerIntentId
|
|
3255
|
+
? { existingTriggerIntentId: conflict.existingTriggerIntentId }
|
|
3256
|
+
: {}),
|
|
3257
|
+
});
|
|
3258
|
+
persistDedupLog.info('Final atomic persistence conflict', {
|
|
3259
|
+
triggerIntentId: finalTriggerIntentId,
|
|
3260
|
+
candidateUserId: candidateActor.userId,
|
|
3261
|
+
existingOpportunityId: conflict.existingOpportunityId,
|
|
3262
|
+
existingTriggerIntentId: conflict.existingTriggerIntentId,
|
|
3263
|
+
existingStatus: conflict.existingStatus,
|
|
3264
|
+
existingAgeMs: Date.now() - new Date(conflict.existingCreatedAt).getTime(),
|
|
3265
|
+
reason: conflict.reason,
|
|
3266
|
+
finalAtomic: true,
|
|
3267
|
+
});
|
|
3268
|
+
}
|
|
3085
3269
|
const allOpportunities = [...reactivatedOpportunities, ...createdList];
|
|
3086
3270
|
persistLog.verbose('Persistence complete', {
|
|
3087
3271
|
created: createdList.length,
|
|
@@ -3089,10 +3273,20 @@ export class OpportunityGraphFactory {
|
|
|
3089
3273
|
existingBetweenActorsCount: existingBetweenActors.length,
|
|
3090
3274
|
status: initialStatus,
|
|
3091
3275
|
});
|
|
3276
|
+
const persistenceOutcome = {
|
|
3277
|
+
evaluatedCount: state.evaluatedOpportunities.length,
|
|
3278
|
+
createdCount: createdList.length,
|
|
3279
|
+
reactivatedCount: reactivatedOpportunities.length,
|
|
3280
|
+
sameTriggerDuplicateSuppressions: existingBetweenActors.filter((entry) => entry.reason === 'same_trigger_recent_duplicate').length,
|
|
3281
|
+
pairActiveNegotiationSuppressions: existingBetweenActors.filter((entry) => entry.reason === 'pair_active_negotiation').length,
|
|
3282
|
+
crossTriggerAllowedCount,
|
|
3283
|
+
finalAtomicConflictCount: conflicts.length,
|
|
3284
|
+
};
|
|
3092
3285
|
return {
|
|
3093
3286
|
opportunities: allOpportunities,
|
|
3094
3287
|
existingBetweenActors,
|
|
3095
3288
|
dedupAlreadyAccepted,
|
|
3289
|
+
persistenceOutcome,
|
|
3096
3290
|
trace: [{
|
|
3097
3291
|
node: "persist",
|
|
3098
3292
|
detail: `Created ${createdList.length}, reactivated ${reactivatedOpportunities.length}, ${existingBetweenActors.length} existing skipped, ${dedupAlreadyAccepted.length} already-accepted pair(s)`,
|
|
@@ -3102,6 +3296,7 @@ export class OpportunityGraphFactory {
|
|
|
3102
3296
|
existingSkipped: existingBetweenActors.length,
|
|
3103
3297
|
alreadyAccepted: dedupAlreadyAccepted.length,
|
|
3104
3298
|
totalOutput: allOpportunities.length,
|
|
3299
|
+
persistenceOutcome,
|
|
3105
3300
|
durationMs: Date.now() - startTime,
|
|
3106
3301
|
},
|
|
3107
3302
|
}],
|