@indexnetwork/protocol 66.0.0-rc.613.1 → 66.0.0
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.
|
@@ -47,14 +47,13 @@ export interface OpportunityCardsDeps {
|
|
|
47
47
|
* @param deps - Database, cache, and presenter.
|
|
48
48
|
* @param opportunity - The opportunity to present.
|
|
49
49
|
* @param viewerId - The viewing user.
|
|
50
|
-
* @param options - `intentId` focuses viewer context on one intent; `skeleton` skips the presenter
|
|
50
|
+
* @param options - `intentId` focuses viewer context on one intent; `skeleton` skips the presenter.
|
|
51
51
|
* @returns The card, or null when the counterpart's name cannot be resolved.
|
|
52
52
|
* @throws When the presenter fails.
|
|
53
53
|
*/
|
|
54
54
|
export declare function presentOpportunityCard(deps: OpportunityCardsDeps, opportunity: Opportunity, viewerId: string, options?: {
|
|
55
55
|
intentId?: string;
|
|
56
56
|
skeleton?: boolean;
|
|
57
|
-
noCache?: boolean;
|
|
58
57
|
}): Promise<OpportunityCard | null>;
|
|
59
58
|
/**
|
|
60
59
|
* List the viewer's opportunities in the given statuses as presented cards,
|
|
@@ -10,6 +10,7 @@ import { canUserSeeOpportunity, isActionableForViewer } from './opportunity.util
|
|
|
10
10
|
import { getPrimaryActionLabel, SECONDARY_ACTION_LABEL } from './opportunity.labels.js';
|
|
11
11
|
const logger = protocolLogger('OpportunityCards');
|
|
12
12
|
const PRESENTATION_CONCURRENCY = 50;
|
|
13
|
+
const CARD_CACHE_TTL = 24 * 60 * 60;
|
|
13
14
|
const ROLE_PRIORITY = new Map([
|
|
14
15
|
['patient', 0],
|
|
15
16
|
['party', 1],
|
|
@@ -36,7 +37,7 @@ function counterpartUserIds(opportunity, viewerId) {
|
|
|
36
37
|
* @param deps - Database, cache, and presenter.
|
|
37
38
|
* @param opportunity - The opportunity to present.
|
|
38
39
|
* @param viewerId - The viewing user.
|
|
39
|
-
* @param options - `intentId` focuses viewer context on one intent; `skeleton` skips the presenter
|
|
40
|
+
* @param options - `intentId` focuses viewer context on one intent; `skeleton` skips the presenter.
|
|
40
41
|
* @returns The card, or null when the counterpart's name cannot be resolved.
|
|
41
42
|
* @throws When the presenter fails.
|
|
42
43
|
*/
|
|
@@ -46,18 +47,6 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
|
|
|
46
47
|
const counterpart = pickDisplayCounterpartActor(opportunity, viewerId);
|
|
47
48
|
if (!counterpart)
|
|
48
49
|
return null;
|
|
49
|
-
const cacheable = opportunity.status !== 'negotiating';
|
|
50
|
-
const cacheKey = buildOpportunityCardCacheKey(opportunity.id, viewerId, options.intentId);
|
|
51
|
-
if (cacheable && !options.skeleton && !options.noCache) {
|
|
52
|
-
try {
|
|
53
|
-
const hit = await deps.cache.get(cacheKey);
|
|
54
|
-
if (hit)
|
|
55
|
-
return { ...hit, status: opportunity.status };
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
logger.warn('card cache read failed, presenting', { opportunityId: opportunity.id, error });
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
50
|
const user = await database.getUser(counterpart.userId).catch(() => null);
|
|
62
51
|
let name = user?.name?.trim();
|
|
63
52
|
if (!name) {
|
|
@@ -89,7 +78,7 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
|
|
|
89
78
|
opportunityStatus: opportunity.status,
|
|
90
79
|
...(negotiationContext ? { negotiationContext } : {}),
|
|
91
80
|
});
|
|
92
|
-
|
|
81
|
+
return {
|
|
93
82
|
...identity,
|
|
94
83
|
mainText: presentation.personalizedSummary,
|
|
95
84
|
cta: presentation.suggestedAction,
|
|
@@ -97,12 +86,6 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
|
|
|
97
86
|
mutualIntentsLabel: presentation.mutualIntentsLabel,
|
|
98
87
|
narratorChip: { name: 'Index', text: presentation.narratorRemark },
|
|
99
88
|
};
|
|
100
|
-
if (cacheable) {
|
|
101
|
-
await deps.cache.set(cacheKey, card).catch((error) => {
|
|
102
|
-
logger.warn('card cache write failed', { opportunityId: opportunity.id, error });
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
return card;
|
|
106
89
|
}
|
|
107
90
|
/**
|
|
108
91
|
* List the viewer's opportunities in the given statuses as presented cards,
|
|
@@ -137,7 +120,7 @@ export async function listOpportunityCards(deps, input) {
|
|
|
137
120
|
return true;
|
|
138
121
|
}).slice(0, input.limit);
|
|
139
122
|
const cacheable = (opp) => opp.status !== 'negotiating';
|
|
140
|
-
const keyFor = (opp) => buildOpportunityCardCacheKey(opp.id, viewerId, intentId);
|
|
123
|
+
const keyFor = (opp) => buildOpportunityCardCacheKey(opp.id, opp.status, viewerId, intentId);
|
|
141
124
|
const cacheableOpps = input.noCache ? [] : opportunities.filter(cacheable);
|
|
142
125
|
const cached = new Map();
|
|
143
126
|
if (cacheableOpps.length > 0) {
|
|
@@ -161,13 +144,9 @@ export async function listOpportunityCards(deps, input) {
|
|
|
161
144
|
if (hit)
|
|
162
145
|
return hit;
|
|
163
146
|
try {
|
|
164
|
-
const card = await presentOpportunityCard(deps, opp, viewerId, {
|
|
165
|
-
intentId,
|
|
166
|
-
skeleton: input.skeleton,
|
|
167
|
-
noCache: input.noCache,
|
|
168
|
-
});
|
|
147
|
+
const card = await presentOpportunityCard(deps, opp, viewerId, { intentId, skeleton: input.skeleton });
|
|
169
148
|
if (card && !card.presentationPending && cacheable(opp)) {
|
|
170
|
-
await deps.cache.set(keyFor(opp), card).catch((error) => {
|
|
149
|
+
await deps.cache.set(keyFor(opp), card, { ttl: CARD_CACHE_TTL }).catch((error) => {
|
|
171
150
|
logger.warn('card cache write failed', { opportunityId: opp.id, error });
|
|
172
151
|
});
|
|
173
152
|
}
|
|
@@ -20,7 +20,7 @@ export interface UserInfo {
|
|
|
20
20
|
}
|
|
21
21
|
/** Cache namespace for opportunity presentation copy. Bump to invalidate copy safety changes. */
|
|
22
22
|
export declare const OPPORTUNITY_PRESENTATION_CACHE_VERSION = "v2";
|
|
23
|
-
export declare function buildOpportunityCardCacheKey(opportunityId: string, viewerId: string, focusedViewerIntentId?: string): string;
|
|
23
|
+
export declare function buildOpportunityCardCacheKey(opportunityId: string, status: string, viewerId: string, focusedViewerIntentId?: string): string;
|
|
24
24
|
export declare function buildApiChatCardPresentationCacheKey(opportunityId: string, viewerId: string): string;
|
|
25
25
|
/**
|
|
26
26
|
* Opportunity Presenter Agent
|
|
@@ -27,9 +27,9 @@ import { createStructuredModel } from "../shared/agent/model.config.js";
|
|
|
27
27
|
// ──────────────────────────────────────────────────────────────────────
|
|
28
28
|
/** Cache namespace for opportunity presentation copy. Bump to invalidate copy safety changes. */
|
|
29
29
|
export const OPPORTUNITY_PRESENTATION_CACHE_VERSION = "v2";
|
|
30
|
-
export function buildOpportunityCardCacheKey(opportunityId, viewerId, focusedViewerIntentId) {
|
|
30
|
+
export function buildOpportunityCardCacheKey(opportunityId, status, viewerId, focusedViewerIntentId) {
|
|
31
31
|
const scope = focusedViewerIntentId ? `:intent:${focusedViewerIntentId}` : "";
|
|
32
|
-
return `card:${opportunityId}:${viewerId}${scope}`;
|
|
32
|
+
return `card:${OPPORTUNITY_PRESENTATION_CACHE_VERSION}:${opportunityId}:${status}:${viewerId}${scope}`;
|
|
33
33
|
}
|
|
34
34
|
export function buildApiChatCardPresentationCacheKey(opportunityId, viewerId) {
|
|
35
35
|
return `chat:${OPPORTUNITY_PRESENTATION_CACHE_VERSION}:card:${opportunityId}:${viewerId}`;
|