@indexnetwork/protocol 66.0.0-rc.611.1 → 66.0.0-rc.615.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.
@@ -47,13 +47,14 @@ 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; `noCache` skips the stored-card read.
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;
57
58
  }): Promise<OpportunityCard | null>;
58
59
  /**
59
60
  * List the viewer's opportunities in the given statuses as presented cards,
@@ -10,7 +10,6 @@ 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;
14
13
  const ROLE_PRIORITY = new Map([
15
14
  ['patient', 0],
16
15
  ['party', 1],
@@ -37,7 +36,7 @@ function counterpartUserIds(opportunity, viewerId) {
37
36
  * @param deps - Database, cache, and presenter.
38
37
  * @param opportunity - The opportunity to present.
39
38
  * @param viewerId - The viewing user.
40
- * @param options - `intentId` focuses viewer context on one intent; `skeleton` skips the presenter.
39
+ * @param options - `intentId` focuses viewer context on one intent; `skeleton` skips the presenter; `noCache` skips the stored-card read.
41
40
  * @returns The card, or null when the counterpart's name cannot be resolved.
42
41
  * @throws When the presenter fails.
43
42
  */
@@ -47,6 +46,18 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
47
46
  const counterpart = pickDisplayCounterpartActor(opportunity, viewerId);
48
47
  if (!counterpart)
49
48
  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
+ }
50
61
  const user = await database.getUser(counterpart.userId).catch(() => null);
51
62
  let name = user?.name?.trim();
52
63
  if (!name) {
@@ -78,7 +89,7 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
78
89
  opportunityStatus: opportunity.status,
79
90
  ...(negotiationContext ? { negotiationContext } : {}),
80
91
  });
81
- return {
92
+ const card = {
82
93
  ...identity,
83
94
  mainText: presentation.personalizedSummary,
84
95
  cta: presentation.suggestedAction,
@@ -86,6 +97,12 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
86
97
  mutualIntentsLabel: presentation.mutualIntentsLabel,
87
98
  narratorChip: { name: 'Index', text: presentation.narratorRemark },
88
99
  };
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;
89
106
  }
90
107
  /**
91
108
  * List the viewer's opportunities in the given statuses as presented cards,
@@ -120,7 +137,7 @@ export async function listOpportunityCards(deps, input) {
120
137
  return true;
121
138
  }).slice(0, input.limit);
122
139
  const cacheable = (opp) => opp.status !== 'negotiating';
123
- const keyFor = (opp) => buildOpportunityCardCacheKey(opp.id, opp.status, viewerId, intentId);
140
+ const keyFor = (opp) => buildOpportunityCardCacheKey(opp.id, viewerId, intentId);
124
141
  const cacheableOpps = input.noCache ? [] : opportunities.filter(cacheable);
125
142
  const cached = new Map();
126
143
  if (cacheableOpps.length > 0) {
@@ -144,9 +161,13 @@ export async function listOpportunityCards(deps, input) {
144
161
  if (hit)
145
162
  return hit;
146
163
  try {
147
- const card = await presentOpportunityCard(deps, opp, viewerId, { intentId, skeleton: input.skeleton });
164
+ const card = await presentOpportunityCard(deps, opp, viewerId, {
165
+ intentId,
166
+ skeleton: input.skeleton,
167
+ noCache: input.noCache,
168
+ });
148
169
  if (card && !card.presentationPending && cacheable(opp)) {
149
- await deps.cache.set(keyFor(opp), card, { ttl: CARD_CACHE_TTL }).catch((error) => {
170
+ await deps.cache.set(keyFor(opp), card).catch((error) => {
150
171
  logger.warn('card cache write failed', { opportunityId: opp.id, error });
151
172
  });
152
173
  }
@@ -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, status: string, viewerId: string, focusedViewerIntentId?: string): string;
23
+ export declare function buildOpportunityCardCacheKey(opportunityId: 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, status, viewerId, focusedViewerIntentId) {
30
+ export function buildOpportunityCardCacheKey(opportunityId, viewerId, focusedViewerIntentId) {
31
31
  const scope = focusedViewerIntentId ? `:intent:${focusedViewerIntentId}` : "";
32
- return `card:${OPPORTUNITY_PRESENTATION_CACHE_VERSION}:${opportunityId}:${status}:${viewerId}${scope}`;
32
+ return `card:${opportunityId}:${viewerId}${scope}`;
33
33
  }
34
34
  export function buildApiChatCardPresentationCacheKey(opportunityId, viewerId) {
35
35
  return `chat:${OPPORTUNITY_PRESENTATION_CACHE_VERSION}:card:${opportunityId}:${viewerId}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indexnetwork/protocol",
3
- "version": "66.0.0-rc.611.1",
3
+ "version": "66.0.0-rc.615.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",