@indexnetwork/protocol 66.0.0-rc.621.1 → 66.0.0-rc.624.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.
|
@@ -31,7 +31,7 @@ export interface AgentDatabase {
|
|
|
31
31
|
* @param updates - Partial set of fields to update.
|
|
32
32
|
* @returns The updated agent record, or null if not found.
|
|
33
33
|
*/
|
|
34
|
-
updateAgent(agentId: string, updates: Partial<Pick<AgentRecord, 'name' | '
|
|
34
|
+
updateAgent(agentId: string, updates: Partial<Pick<AgentRecord, 'name' | 'status' | 'metadata'>>): Promise<AgentRecord | null>;
|
|
35
35
|
/**
|
|
36
36
|
* Deletes an agent.
|
|
37
37
|
* @param agentId - The agent UUID.
|
|
@@ -10,7 +10,6 @@ export interface AgentRecord {
|
|
|
10
10
|
id: string;
|
|
11
11
|
ownerId: string;
|
|
12
12
|
name: string;
|
|
13
|
-
description: string | null;
|
|
14
13
|
type: 'external' | 'system';
|
|
15
14
|
status: 'active' | 'inactive';
|
|
16
15
|
metadata: Record<string, unknown>;
|
|
@@ -20,7 +19,6 @@ export interface AgentRecord {
|
|
|
20
19
|
export interface CreateAgentInput {
|
|
21
20
|
ownerId: string;
|
|
22
21
|
name: string;
|
|
23
|
-
description?: string;
|
|
24
22
|
type: 'external' | 'system';
|
|
25
23
|
metadata?: Record<string, unknown>;
|
|
26
24
|
}
|
|
@@ -29,6 +29,8 @@ export interface OpportunityCard {
|
|
|
29
29
|
};
|
|
30
30
|
/** Viewer's role in this opportunity (e.g. 'party', 'agent', 'patient', 'peer'). */
|
|
31
31
|
viewerRole?: string;
|
|
32
|
+
/** This viewer already committed. Status can still be pending until the other person accepts. */
|
|
33
|
+
viewerCommitted?: boolean;
|
|
32
34
|
/**
|
|
33
35
|
* True for a skeleton card: identity fields are real but mainText/cta are
|
|
34
36
|
* empty because the presenter was skipped. Never cached.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { protocolLogger } from '../shared/observability/protocol.logger.js';
|
|
7
7
|
import { buildOpportunityCardCacheKey, gatherPresenterContext } from './opportunity.presentation.js';
|
|
8
8
|
import { loadNegotiationContext } from './negotiation-context.loader.js';
|
|
9
|
-
import { canUserSeeOpportunity
|
|
9
|
+
import { canUserSeeOpportunity } from './opportunity.utils.js';
|
|
10
10
|
import { getPrimaryActionLabel, SECONDARY_ACTION_LABEL } from './opportunity.labels.js';
|
|
11
11
|
const logger = protocolLogger('OpportunityCards');
|
|
12
12
|
const PRESENTATION_CONCURRENCY = 50;
|
|
@@ -30,6 +30,12 @@ function pickDisplayCounterpartActor(opportunity, viewerId) {
|
|
|
30
30
|
function counterpartUserIds(opportunity, viewerId) {
|
|
31
31
|
return new Set(opportunity.actors.map((a) => a.userId).filter((id) => id && id !== viewerId));
|
|
32
32
|
}
|
|
33
|
+
function viewerHasCommitted(opportunity, viewerId) {
|
|
34
|
+
return (opportunity.committedActorIds ?? []).includes(viewerId);
|
|
35
|
+
}
|
|
36
|
+
function stampViewerCommitted(card, viewerCommitted) {
|
|
37
|
+
return { ...card, viewerCommitted };
|
|
38
|
+
}
|
|
33
39
|
/**
|
|
34
40
|
* Present one opportunity as a card for the viewer.
|
|
35
41
|
*
|
|
@@ -46,13 +52,14 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
|
|
|
46
52
|
const counterpart = pickDisplayCounterpartActor(opportunity, viewerId);
|
|
47
53
|
if (!counterpart)
|
|
48
54
|
return null;
|
|
55
|
+
const viewerCommitted = viewerHasCommitted(opportunity, viewerId);
|
|
49
56
|
const cacheable = opportunity.status !== 'negotiating';
|
|
50
57
|
const cacheKey = buildOpportunityCardCacheKey(opportunity.id, viewerId, options.intentId);
|
|
51
58
|
if (cacheable && !options.skeleton && !options.noCache) {
|
|
52
59
|
try {
|
|
53
60
|
const hit = await deps.cache.get(cacheKey);
|
|
54
61
|
if (hit)
|
|
55
|
-
return { ...hit, status: opportunity.status };
|
|
62
|
+
return stampViewerCommitted({ ...hit, status: opportunity.status }, viewerCommitted);
|
|
56
63
|
}
|
|
57
64
|
catch (error) {
|
|
58
65
|
logger.warn('card cache read failed, presenting', { opportunityId: opportunity.id, error });
|
|
@@ -78,7 +85,7 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
|
|
|
78
85
|
viewerRole,
|
|
79
86
|
};
|
|
80
87
|
if (options.skeleton) {
|
|
81
|
-
return { ...identity, mainText: '', cta: '', mutualIntentsLabel: 'Shared interests', presentationPending: true };
|
|
88
|
+
return stampViewerCommitted({ ...identity, mainText: '', cta: '', mutualIntentsLabel: 'Shared interests', presentationPending: true }, viewerCommitted);
|
|
82
89
|
}
|
|
83
90
|
const [context, negotiationContext] = await Promise.all([
|
|
84
91
|
gatherPresenterContext(database, opportunity, viewerId, counterpart.userId, options.intentId),
|
|
@@ -89,14 +96,14 @@ export async function presentOpportunityCard(deps, opportunity, viewerId, option
|
|
|
89
96
|
opportunityStatus: opportunity.status,
|
|
90
97
|
...(negotiationContext ? { negotiationContext } : {}),
|
|
91
98
|
});
|
|
92
|
-
const card = {
|
|
99
|
+
const card = stampViewerCommitted({
|
|
93
100
|
...identity,
|
|
94
101
|
mainText: presentation.personalizedSummary,
|
|
95
102
|
cta: presentation.suggestedAction,
|
|
96
103
|
headline: presentation.headline,
|
|
97
104
|
mutualIntentsLabel: presentation.mutualIntentsLabel,
|
|
98
105
|
narratorChip: { name: 'Index', text: presentation.narratorRemark },
|
|
99
|
-
};
|
|
106
|
+
}, viewerCommitted);
|
|
100
107
|
if (cacheable) {
|
|
101
108
|
await deps.cache.set(cacheKey, card).catch((error) => {
|
|
102
109
|
logger.warn('card cache write failed', { opportunityId: opportunity.id, error });
|
|
@@ -124,8 +131,6 @@ export async function listOpportunityCards(deps, input) {
|
|
|
124
131
|
const requested = new Set(input.statuses);
|
|
125
132
|
const visible = raw
|
|
126
133
|
.filter((opp) => requested.has(opp.status) && canUserSeeOpportunity(opp.actors, opp.status, viewerId))
|
|
127
|
-
.filter((opp) => opp.status !== 'pending'
|
|
128
|
-
|| isActionableForViewer(opp.actors, opp.status, viewerId, opp.committedActorIds ?? []))
|
|
129
134
|
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
130
135
|
const seen = new Set();
|
|
131
136
|
const opportunities = visible.filter((opp) => {
|
|
@@ -146,7 +151,7 @@ export async function listOpportunityCards(deps, input) {
|
|
|
146
151
|
cacheableOpps.forEach((opp, i) => {
|
|
147
152
|
const hit = hits[i];
|
|
148
153
|
if (hit)
|
|
149
|
-
cached.set(opp.id, { ...hit, status: opp.status });
|
|
154
|
+
cached.set(opp.id, stampViewerCommitted({ ...hit, status: opp.status }, viewerHasCommitted(opp, viewerId)));
|
|
150
155
|
});
|
|
151
156
|
}
|
|
152
157
|
catch (error) {
|