@indexnetwork/protocol 6.6.1-rc.387.1 → 6.6.3-rc.389.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 +1 -0
- package/dist/opportunity/discriminator/discriminator.adjustments.js +1 -1
- package/dist/opportunity/discriminator/discriminator.adjustments.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 +198 -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.safe-presentation.d.ts +1 -1
- package/dist/opportunity/opportunity.safe-presentation.js +1 -1
- package/dist/opportunity/opportunity.safe-presentation.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 +25 -2
- 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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Shared persist phase for opportunity creation: enrichOrCreate → create (or create+expire) → optional chat injection.
|
|
3
3
|
* Used by the opportunity graph persist node and by the manual opportunity service for consistency.
|
|
4
4
|
*/
|
|
5
|
-
import type { CreateOpportunityData, Opportunity, OpportunityNetworkEligibility, OpportunityStatus } from '../shared/interfaces/database.interface.js';
|
|
5
|
+
import type { CreateOpportunityData, IntentScopedOpportunityPersistenceResult, Opportunity, OpportunityDedupConflict, OpportunityNetworkEligibility, OpportunityStatus } from '../shared/interfaces/database.interface.js';
|
|
6
6
|
import type { Embedder } from '../shared/interfaces/embedder.interface.js';
|
|
7
7
|
import type { EnricherDatabase } from './opportunity.enricher.js';
|
|
8
8
|
export type PersistOpportunityDatabase = EnricherDatabase & {
|
|
@@ -17,6 +17,9 @@ export type PersistOpportunityDatabase = EnricherDatabase & {
|
|
|
17
17
|
created: Opportunity;
|
|
18
18
|
expired: Opportunity[];
|
|
19
19
|
} | null>;
|
|
20
|
+
persistIntentScopedOpportunityIfNetworkEligible?(data: CreateOpportunityData, expireIds: string[], eligibility: OpportunityNetworkEligibility & {
|
|
21
|
+
triggerIntentId: string;
|
|
22
|
+
}, dedupWindowMs: number): Promise<IntentScopedOpportunityPersistenceResult | null>;
|
|
20
23
|
/** Optional: used to populate expired list in non-atomic path. */
|
|
21
24
|
getOpportunity?(id: string): Promise<Opportunity | null>;
|
|
22
25
|
};
|
|
@@ -27,14 +30,24 @@ export interface PersistOpportunitiesParams {
|
|
|
27
30
|
injectChat?: (opportunity: Opportunity) => Promise<unknown>;
|
|
28
31
|
/** Require adapter-level membership/assignment locks for discovery-created rows. */
|
|
29
32
|
networkEligibility?: OpportunityNetworkEligibility;
|
|
33
|
+
/** Scope dedup/enrichment and the final atomic re-check to one owned intent. */
|
|
34
|
+
intentDedupScope?: {
|
|
35
|
+
triggerIntentId: string;
|
|
36
|
+
dedupWindowMs: number;
|
|
37
|
+
};
|
|
30
38
|
}
|
|
31
39
|
export interface PersistOpportunitiesError {
|
|
32
40
|
itemIndex: number;
|
|
33
41
|
error: unknown;
|
|
34
42
|
}
|
|
43
|
+
export interface PersistOpportunitiesConflict extends OpportunityDedupConflict {
|
|
44
|
+
itemIndex: number;
|
|
45
|
+
finalAtomic: true;
|
|
46
|
+
}
|
|
35
47
|
export interface PersistOpportunitiesResult {
|
|
36
48
|
created: Opportunity[];
|
|
37
49
|
expired: Opportunity[];
|
|
50
|
+
conflicts: PersistOpportunitiesConflict[];
|
|
38
51
|
errors?: PersistOpportunitiesError[];
|
|
39
52
|
}
|
|
40
53
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity.persist.d.ts","sourceRoot":"/","sources":["opportunity/opportunity.persist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,6BAA6B,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;
|
|
1
|
+
{"version":3,"file":"opportunity.persist.d.ts","sourceRoot":"/","sources":["opportunity/opportunity.persist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,wCAAwC,EAAE,WAAW,EAAE,wBAAwB,EAAE,6BAA6B,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAC3N,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4CAA4C,CAAC;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAOlE,MAAM,MAAM,0BAA0B,GAAG,gBAAgB,GAAG;IAC1D,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACrE,kCAAkC,CAAC,CACjC,IAAI,EAAE,qBAAqB,EAC3B,WAAW,EAAE,6BAA6B,GACzC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC/B,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,GAAG,WAAW,GAAG,IAAI,CAAC,CAAC;IACnG,6BAA6B,CAAC,CAC5B,IAAI,EAAE,qBAAqB,EAC3B,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC,CAAC;IAC7D,8CAA8C,CAAC,CAC7C,IAAI,EAAE,qBAAqB,EAC3B,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,6BAA6B,GACzC,OAAO,CAAC;QAAE,OAAO,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,WAAW,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACpE,+CAA+C,CAAC,CAC9C,IAAI,EAAE,qBAAqB,EAC3B,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,6BAA6B,GAAG;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE,EACxE,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,wCAAwC,GAAG,IAAI,CAAC,CAAC;IAC5D,kEAAkE;IAClE,cAAc,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,oFAAoF;IACpF,kBAAkB,CAAC,EAAE,6BAA6B,CAAC;IACnD,gFAAgF;IAChF,gBAAgB,CAAC,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACvE;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,4BAA6B,SAAQ,wBAAwB;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,4BAA4B,EAAE,CAAC;IAC1C,MAAM,CAAC,EAAE,yBAAyB,EAAE,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA4GlH"}
|
|
@@ -12,20 +12,49 @@ const logger = protocolLogger('OpportunityPersist');
|
|
|
12
12
|
* Returns both created and expired so callers can emit events (e.g. manual service).
|
|
13
13
|
*/
|
|
14
14
|
export async function persistOpportunities(params) {
|
|
15
|
-
const { database, embedder, items, injectChat, networkEligibility } = params;
|
|
15
|
+
const { database, embedder, items, injectChat, networkEligibility, intentDedupScope } = params;
|
|
16
16
|
const created = [];
|
|
17
17
|
const expired = [];
|
|
18
|
+
const conflicts = [];
|
|
18
19
|
const errors = [];
|
|
19
20
|
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
20
21
|
const data = items[itemIndex];
|
|
21
22
|
try {
|
|
22
23
|
const normalizedData = normalizeCreateOpportunityActorIntents(data);
|
|
23
|
-
|
|
24
|
+
if (intentDedupScope
|
|
25
|
+
&& intentDedupScope.triggerIntentId !== networkEligibility?.triggerIntentId) {
|
|
26
|
+
throw new Error('Intent-scoped dedup trigger must match network eligibility');
|
|
27
|
+
}
|
|
28
|
+
const enrichment = await enrichOrCreate(database, embedder, normalizedData, intentDedupScope && networkEligibility
|
|
29
|
+
? {
|
|
30
|
+
ownedIntentScope: {
|
|
31
|
+
triggerIntentId: intentDedupScope.triggerIntentId,
|
|
32
|
+
ownerUserId: networkEligibility.ownerUserId,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
: undefined);
|
|
24
36
|
const toCreate = normalizeCreateOpportunityActorIntents(enrichment.data);
|
|
25
37
|
if (enrichment.enriched) {
|
|
26
38
|
toCreate.status = enrichment.resolvedStatus;
|
|
27
39
|
}
|
|
28
|
-
if (
|
|
40
|
+
if (intentDedupScope) {
|
|
41
|
+
if (!networkEligibility?.triggerIntentId) {
|
|
42
|
+
throw new Error('Intent-scoped dedup requires trigger-intent network eligibility');
|
|
43
|
+
}
|
|
44
|
+
if (!database.persistIntentScopedOpportunityIfNetworkEligible) {
|
|
45
|
+
throw new Error('Intent-scoped atomic persistence is required for owned-intent discovery');
|
|
46
|
+
}
|
|
47
|
+
const result = await database.persistIntentScopedOpportunityIfNetworkEligible(toCreate, enrichment.enriched ? enrichment.expiredIds : [], { ...networkEligibility, triggerIntentId: networkEligibility.triggerIntentId }, intentDedupScope.dedupWindowMs);
|
|
48
|
+
if (!result)
|
|
49
|
+
continue;
|
|
50
|
+
if ('conflict' in result) {
|
|
51
|
+
conflicts.push({ itemIndex, finalAtomic: true, ...result.conflict });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
created.push(result.created);
|
|
55
|
+
expired.push(...result.expired);
|
|
56
|
+
}
|
|
57
|
+
else if (networkEligibility) {
|
|
29
58
|
if (enrichment.enriched && enrichment.expiredIds.length > 0) {
|
|
30
59
|
if (!database.createOpportunityAndExpireIdsIfNetworkEligible) {
|
|
31
60
|
throw new Error('Network-eligible create+expire is required for discovery persistence');
|
|
@@ -81,6 +110,6 @@ export async function persistOpportunities(params) {
|
|
|
81
110
|
logger.warn('Item failed', { itemIndex, error: err });
|
|
82
111
|
}
|
|
83
112
|
}
|
|
84
|
-
return { created, expired, ...(errors.length > 0 ? { errors } : {}) };
|
|
113
|
+
return { created, expired, conflicts, ...(errors.length > 0 ? { errors } : {}) };
|
|
85
114
|
}
|
|
86
115
|
//# sourceMappingURL=opportunity.persist.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity.persist.js","sourceRoot":"/","sources":["opportunity/opportunity.persist.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared persist phase for opportunity creation: enrichOrCreate → create (or create+expire) → optional chat injection.\n * Used by the opportunity graph persist node and by the manual opportunity service for consistency.\n */\n\nimport type { CreateOpportunityData, Opportunity, OpportunityNetworkEligibility, OpportunityStatus } from '../shared/interfaces/database.interface.js';\nimport type { Embedder } from '../shared/interfaces/embedder.interface.js';\nimport type { EnricherDatabase } from './opportunity.enricher.js';\nimport { enrichOrCreate } from './opportunity.enricher.js';\nimport { normalizeCreateOpportunityActorIntents } from './opportunity.actor.js';\nimport { protocolLogger } from '../shared/observability/protocol.logger.js';\n\nconst logger = protocolLogger('OpportunityPersist');\n\nexport type PersistOpportunityDatabase = EnricherDatabase & {\n createOpportunity(data: CreateOpportunityData): Promise<Opportunity>;\n createOpportunityIfNetworkEligible?(\n data: CreateOpportunityData,\n eligibility: OpportunityNetworkEligibility,\n ): Promise<Opportunity | null>;\n updateOpportunityStatus(id: string, status: OpportunityStatus): Promise<void | Opportunity | null>;\n createOpportunityAndExpireIds?(\n data: CreateOpportunityData,\n expireIds: string[]\n ): Promise<{ created: Opportunity; expired: Opportunity[] }>;\n createOpportunityAndExpireIdsIfNetworkEligible?(\n data: CreateOpportunityData,\n expireIds: string[],\n eligibility: OpportunityNetworkEligibility,\n ): Promise<{ created: Opportunity; expired: Opportunity[] } | null>;\n /** Optional: used to populate expired list in non-atomic path. */\n getOpportunity?(id: string): Promise<Opportunity | null>;\n};\n\nexport interface PersistOpportunitiesParams {\n database: PersistOpportunityDatabase;\n embedder: Embedder;\n items: CreateOpportunityData[];\n injectChat?: (opportunity: Opportunity) => Promise<unknown>;\n /** Require adapter-level membership/assignment locks for discovery-created rows. */\n networkEligibility?: OpportunityNetworkEligibility;\n}\n\nexport interface PersistOpportunitiesError {\n itemIndex: number;\n error: unknown;\n}\n\nexport interface PersistOpportunitiesResult {\n created: Opportunity[];\n expired: Opportunity[];\n errors?: PersistOpportunitiesError[];\n}\n\n/**\n * Persist one or more opportunities: enrich (merge overlapping), create, expire replaced, optional chat injection.\n * When the database has createOpportunityAndExpireIds and enrichment produced expireIds, uses it for atomic create+expire.\n * Returns both created and expired so callers can emit events (e.g. manual service).\n */\nexport async function persistOpportunities(params: PersistOpportunitiesParams): Promise<PersistOpportunitiesResult> {\n const { database, embedder, items, injectChat, networkEligibility } = params;\n const created: Opportunity[] = [];\n const expired: Opportunity[] = [];\n const errors: PersistOpportunitiesError[] = [];\n\n for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n const data = items[itemIndex];\n try {\n const normalizedData = normalizeCreateOpportunityActorIntents(data);\n const enrichment = await enrichOrCreate(database, embedder, normalizedData);\n const toCreate = normalizeCreateOpportunityActorIntents(enrichment.data);\n if (enrichment.enriched) {\n toCreate.status = enrichment.resolvedStatus;\n }\n\n if (networkEligibility) {\n if (enrichment.enriched && enrichment.expiredIds.length > 0) {\n if (!database.createOpportunityAndExpireIdsIfNetworkEligible) {\n throw new Error('Network-eligible create+expire is required for discovery persistence');\n }\n const result = await database.createOpportunityAndExpireIdsIfNetworkEligible(\n toCreate,\n enrichment.expiredIds,\n networkEligibility,\n );\n if (!result) continue;\n created.push(result.created);\n expired.push(...result.expired);\n } else {\n if (!database.createOpportunityIfNetworkEligible) {\n throw new Error('Network-eligible create is required for discovery persistence');\n }\n const c = await database.createOpportunityIfNetworkEligible(toCreate, networkEligibility);\n if (!c) continue;\n created.push(c);\n }\n } else if (\n database.createOpportunityAndExpireIds &&\n enrichment.enriched &&\n enrichment.expiredIds.length > 0\n ) {\n const result = await database.createOpportunityAndExpireIds(toCreate, enrichment.expiredIds);\n created.push(result.created);\n expired.push(...result.expired);\n } else {\n const c = await database.createOpportunity(toCreate);\n created.push(c);\n if (enrichment.enriched && enrichment.expiredIds.length > 0) {\n for (const id of enrichment.expiredIds) {\n await database.updateOpportunityStatus(id, 'expired');\n }\n if (database.getOpportunity) {\n for (const id of enrichment.expiredIds) {\n const opp = await database.getOpportunity(id);\n if (opp) expired.push(opp);\n }\n }\n }\n }\n\n const lastCreated = created[created.length - 1];\n if (lastCreated?.status === 'pending' && injectChat) {\n await injectChat(lastCreated).catch((err) => {\n logger.warn('Chat injection failed', { opportunityId: lastCreated.id, error: err });\n });\n }\n } catch (err) {\n errors.push({ itemIndex, error: err });\n logger.warn('Item failed', { itemIndex, error: err });\n }\n }\n\n return { created, expired, ...(errors.length > 0 ? { errors } : {}) };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"opportunity.persist.js","sourceRoot":"/","sources":["opportunity/opportunity.persist.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared persist phase for opportunity creation: enrichOrCreate → create (or create+expire) → optional chat injection.\n * Used by the opportunity graph persist node and by the manual opportunity service for consistency.\n */\n\nimport type { CreateOpportunityData, IntentScopedOpportunityPersistenceResult, Opportunity, OpportunityDedupConflict, OpportunityNetworkEligibility, OpportunityStatus } from '../shared/interfaces/database.interface.js';\nimport type { Embedder } from '../shared/interfaces/embedder.interface.js';\nimport type { EnricherDatabase } from './opportunity.enricher.js';\nimport { enrichOrCreate } from './opportunity.enricher.js';\nimport { normalizeCreateOpportunityActorIntents } from './opportunity.actor.js';\nimport { protocolLogger } from '../shared/observability/protocol.logger.js';\n\nconst logger = protocolLogger('OpportunityPersist');\n\nexport type PersistOpportunityDatabase = EnricherDatabase & {\n createOpportunity(data: CreateOpportunityData): Promise<Opportunity>;\n createOpportunityIfNetworkEligible?(\n data: CreateOpportunityData,\n eligibility: OpportunityNetworkEligibility,\n ): Promise<Opportunity | null>;\n updateOpportunityStatus(id: string, status: OpportunityStatus): Promise<void | Opportunity | null>;\n createOpportunityAndExpireIds?(\n data: CreateOpportunityData,\n expireIds: string[]\n ): Promise<{ created: Opportunity; expired: Opportunity[] }>;\n createOpportunityAndExpireIdsIfNetworkEligible?(\n data: CreateOpportunityData,\n expireIds: string[],\n eligibility: OpportunityNetworkEligibility,\n ): Promise<{ created: Opportunity; expired: Opportunity[] } | null>;\n persistIntentScopedOpportunityIfNetworkEligible?(\n data: CreateOpportunityData,\n expireIds: string[],\n eligibility: OpportunityNetworkEligibility & { triggerIntentId: string },\n dedupWindowMs: number,\n ): Promise<IntentScopedOpportunityPersistenceResult | null>;\n /** Optional: used to populate expired list in non-atomic path. */\n getOpportunity?(id: string): Promise<Opportunity | null>;\n};\n\nexport interface PersistOpportunitiesParams {\n database: PersistOpportunityDatabase;\n embedder: Embedder;\n items: CreateOpportunityData[];\n injectChat?: (opportunity: Opportunity) => Promise<unknown>;\n /** Require adapter-level membership/assignment locks for discovery-created rows. */\n networkEligibility?: OpportunityNetworkEligibility;\n /** Scope dedup/enrichment and the final atomic re-check to one owned intent. */\n intentDedupScope?: { triggerIntentId: string; dedupWindowMs: number };\n}\n\nexport interface PersistOpportunitiesError {\n itemIndex: number;\n error: unknown;\n}\n\nexport interface PersistOpportunitiesConflict extends OpportunityDedupConflict {\n itemIndex: number;\n finalAtomic: true;\n}\n\nexport interface PersistOpportunitiesResult {\n created: Opportunity[];\n expired: Opportunity[];\n conflicts: PersistOpportunitiesConflict[];\n errors?: PersistOpportunitiesError[];\n}\n\n/**\n * Persist one or more opportunities: enrich (merge overlapping), create, expire replaced, optional chat injection.\n * When the database has createOpportunityAndExpireIds and enrichment produced expireIds, uses it for atomic create+expire.\n * Returns both created and expired so callers can emit events (e.g. manual service).\n */\nexport async function persistOpportunities(params: PersistOpportunitiesParams): Promise<PersistOpportunitiesResult> {\n const { database, embedder, items, injectChat, networkEligibility, intentDedupScope } = params;\n const created: Opportunity[] = [];\n const expired: Opportunity[] = [];\n const conflicts: PersistOpportunitiesConflict[] = [];\n const errors: PersistOpportunitiesError[] = [];\n\n for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n const data = items[itemIndex];\n try {\n const normalizedData = normalizeCreateOpportunityActorIntents(data);\n if (\n intentDedupScope\n && intentDedupScope.triggerIntentId !== networkEligibility?.triggerIntentId\n ) {\n throw new Error('Intent-scoped dedup trigger must match network eligibility');\n }\n const enrichment = await enrichOrCreate(database, embedder, normalizedData, intentDedupScope && networkEligibility\n ? {\n ownedIntentScope: {\n triggerIntentId: intentDedupScope.triggerIntentId,\n ownerUserId: networkEligibility.ownerUserId,\n },\n }\n : undefined);\n const toCreate = normalizeCreateOpportunityActorIntents(enrichment.data);\n if (enrichment.enriched) {\n toCreate.status = enrichment.resolvedStatus;\n }\n\n if (intentDedupScope) {\n if (!networkEligibility?.triggerIntentId) {\n throw new Error('Intent-scoped dedup requires trigger-intent network eligibility');\n }\n if (!database.persistIntentScopedOpportunityIfNetworkEligible) {\n throw new Error('Intent-scoped atomic persistence is required for owned-intent discovery');\n }\n const result = await database.persistIntentScopedOpportunityIfNetworkEligible(\n toCreate,\n enrichment.enriched ? enrichment.expiredIds : [],\n { ...networkEligibility, triggerIntentId: networkEligibility.triggerIntentId },\n intentDedupScope.dedupWindowMs,\n );\n if (!result) continue;\n if ('conflict' in result) {\n conflicts.push({ itemIndex, finalAtomic: true, ...result.conflict });\n continue;\n }\n created.push(result.created);\n expired.push(...result.expired);\n } else if (networkEligibility) {\n if (enrichment.enriched && enrichment.expiredIds.length > 0) {\n if (!database.createOpportunityAndExpireIdsIfNetworkEligible) {\n throw new Error('Network-eligible create+expire is required for discovery persistence');\n }\n const result = await database.createOpportunityAndExpireIdsIfNetworkEligible(\n toCreate,\n enrichment.expiredIds,\n networkEligibility,\n );\n if (!result) continue;\n created.push(result.created);\n expired.push(...result.expired);\n } else {\n if (!database.createOpportunityIfNetworkEligible) {\n throw new Error('Network-eligible create is required for discovery persistence');\n }\n const c = await database.createOpportunityIfNetworkEligible(toCreate, networkEligibility);\n if (!c) continue;\n created.push(c);\n }\n } else if (\n database.createOpportunityAndExpireIds &&\n enrichment.enriched &&\n enrichment.expiredIds.length > 0\n ) {\n const result = await database.createOpportunityAndExpireIds(toCreate, enrichment.expiredIds);\n created.push(result.created);\n expired.push(...result.expired);\n } else {\n const c = await database.createOpportunity(toCreate);\n created.push(c);\n if (enrichment.enriched && enrichment.expiredIds.length > 0) {\n for (const id of enrichment.expiredIds) {\n await database.updateOpportunityStatus(id, 'expired');\n }\n if (database.getOpportunity) {\n for (const id of enrichment.expiredIds) {\n const opp = await database.getOpportunity(id);\n if (opp) expired.push(opp);\n }\n }\n }\n }\n\n const lastCreated = created[created.length - 1];\n if (lastCreated?.status === 'pending' && injectChat) {\n await injectChat(lastCreated).catch((err) => {\n logger.warn('Chat injection failed', { opportunityId: lastCreated.id, error: err });\n });\n }\n } catch (err) {\n errors.push({ itemIndex, error: err });\n logger.warn('Item failed', { itemIndex, error: err });\n }\n }\n\n return { created, expired, conflicts, ...(errors.length > 0 ? { errors } : {}) };\n}\n"]}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Surfaces choose *policy* (send a sanitized fallback vs skip entirely) via
|
|
17
17
|
* `allowFallback`; they no longer choose (or forget) sanitization steps.
|
|
18
18
|
*
|
|
19
|
-
* See `.pi/skills/opportunity-presentation
|
|
19
|
+
* See `.pi/skills/review-opportunity-presentation/SKILL.md` for the review
|
|
20
20
|
* checklist this module exists to satisfy.
|
|
21
21
|
*/
|
|
22
22
|
/** Default max length for fallback summaries (matches presenter internal fallback). */
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Surfaces choose *policy* (send a sanitized fallback vs skip entirely) via
|
|
17
17
|
* `allowFallback`; they no longer choose (or forget) sanitization steps.
|
|
18
18
|
*
|
|
19
|
-
* See `.pi/skills/opportunity-presentation
|
|
19
|
+
* See `.pi/skills/review-opportunity-presentation/SKILL.md` for the review
|
|
20
20
|
* checklist this module exists to satisfy.
|
|
21
21
|
*/
|
|
22
22
|
import { truncateAtBoundary, viewerCentricCardSummary } from "./opportunity.presentation.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity.safe-presentation.js","sourceRoot":"/","sources":["opportunity/opportunity.safe-presentation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,iCAAiC,EAAE,MAAM,+BAA+B,CAAC;AAElF,uFAAuF;AACvF,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,2BAA2B,GAAG,yBAAyB,CAAC;AAErE,yFAAyF;AACzF,MAAM,CAAC,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAElE,oFAAoF;AACpF,MAAM,CAAC,MAAM,uBAAuB,GAClC,8CAA8C,CAAC;AAejD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAAuC,EACvC,OAA4B,EAAE;IAE9B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,uBAAuB,CAAC;IAE1D,MAAM,UAAU,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpE,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,cAAc,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;IACrE,IAAI,CAAC,cAAc;QAAE,OAAO,SAAS,CAAC;IAEtC,sEAAsE;IACtE,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,SAAS,GAAG,wBAAwB,CACxC,cAAc,EACd,IAAI,CAAC,eAAe,IAAI,EAAE,EAC1B,MAAM,CAAC,iBAAiB,EACxB,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,cAAc,IAAI,SAAS,CACjC,CAAC;IAEF,8EAA8E;IAC9E,0EAA0E;IAC1E,iDAAiD;IACjD,MAAM,SAAS,GAAG,iCAAiC,CAAC,SAAS,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,kBAAkB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC1D,OAAO,SAAS,IAAI,SAAS,CAAC;AAChC,CAAC;AAuCD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAA8B,EAC9B,OAAgC,EAAE;IAElC,MAAM,SAAS,GAAG,MAAM,CAAC,oBAAoB,CAAC;IAC9C,IAAI,SAAS,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QACpE,MAAM,OAAO,GAAG,iCAAiC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACjF,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO;gBACL,QAAQ,EACN,iCAAiC,CAAC,SAAS,CAAC,QAAQ,CAAC;oBACrD,yBAAyB;gBAC3B,OAAO;gBACP,eAAe,EACb,iCAAiC,CAAC,SAAS,CAAC,eAAe,CAAC;oBAC5D,uBAAuB;gBACzB,UAAU,EAAE,KAAK;aAClB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,aAAa,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAE9C,MAAM,YAAY,GAChB,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,cAAc,EAAE,SAAS,IAAI,EAAE,CAAC;IAC/D,OAAO;QACL,QAAQ,EAAE,yBAAyB;QACnC,OAAO,EAAE,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC;QAChD,eAAe,EAAE,uBAAuB;QACxC,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Shared safe-presentation primitive for all user-facing opportunity surfaces.\n *\n * Historically every surface (home feed, list/discover cards, minimal chat\n * cards, notification emails/Telegram, chat context, delivery cards) invented\n * its own fallback chain for the case where genuine LLM presenter output is\n * unavailable — some sliced raw `interpretation.reasoning` with no\n * sanitization at all. This module is the single standard:\n *\n * raw reasoning\n * → whitespace-normalize\n * → viewer-centric rewrite (incl. UUID stripping + introducer-mention stripping)\n * → boundary-aware truncation\n * → per-surface empty-text default\n *\n * Surfaces choose *policy* (send a sanitized fallback vs skip entirely) via\n * `allowFallback`; they no longer choose (or forget) sanitization steps.\n *\n * See `.pi/skills/opportunity-presentation
|
|
1
|
+
{"version":3,"file":"opportunity.safe-presentation.js","sourceRoot":"/","sources":["opportunity/opportunity.safe-presentation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,iCAAiC,EAAE,MAAM,+BAA+B,CAAC;AAElF,uFAAuF;AACvF,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,2BAA2B,GAAG,yBAAyB,CAAC;AAErE,yFAAyF;AACzF,MAAM,CAAC,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAElE,oFAAoF;AACpF,MAAM,CAAC,MAAM,uBAAuB,GAClC,8CAA8C,CAAC;AAejD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAAuC,EACvC,OAA4B,EAAE;IAE9B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,2BAA2B,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,uBAAuB,CAAC;IAE1D,MAAM,UAAU,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpE,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,cAAc,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;IACrE,IAAI,CAAC,cAAc;QAAE,OAAO,SAAS,CAAC;IAEtC,sEAAsE;IACtE,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,SAAS,GAAG,wBAAwB,CACxC,cAAc,EACd,IAAI,CAAC,eAAe,IAAI,EAAE,EAC1B,MAAM,CAAC,iBAAiB,EACxB,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,cAAc,IAAI,SAAS,CACjC,CAAC;IAEF,8EAA8E;IAC9E,0EAA0E;IAC1E,iDAAiD;IACjD,MAAM,SAAS,GAAG,iCAAiC,CAAC,SAAS,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,kBAAkB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC1D,OAAO,SAAS,IAAI,SAAS,CAAC;AAChC,CAAC;AAuCD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAA8B,EAC9B,OAAgC,EAAE;IAElC,MAAM,SAAS,GAAG,MAAM,CAAC,oBAAoB,CAAC;IAC9C,IAAI,SAAS,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QACpE,MAAM,OAAO,GAAG,iCAAiC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACjF,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO;gBACL,QAAQ,EACN,iCAAiC,CAAC,SAAS,CAAC,QAAQ,CAAC;oBACrD,yBAAyB;gBAC3B,OAAO;gBACP,eAAe,EACb,iCAAiC,CAAC,SAAS,CAAC,eAAe,CAAC;oBAC5D,uBAAuB;gBACzB,UAAU,EAAE,KAAK;aAClB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,aAAa,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAE9C,MAAM,YAAY,GAChB,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,cAAc,EAAE,SAAS,IAAI,EAAE,CAAC;IAC/D,OAAO;QACL,QAAQ,EAAE,yBAAyB;QACnC,OAAO,EAAE,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC;QAChD,eAAe,EAAE,uBAAuB;QACxC,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Shared safe-presentation primitive for all user-facing opportunity surfaces.\n *\n * Historically every surface (home feed, list/discover cards, minimal chat\n * cards, notification emails/Telegram, chat context, delivery cards) invented\n * its own fallback chain for the case where genuine LLM presenter output is\n * unavailable — some sliced raw `interpretation.reasoning` with no\n * sanitization at all. This module is the single standard:\n *\n * raw reasoning\n * → whitespace-normalize\n * → viewer-centric rewrite (incl. UUID stripping + introducer-mention stripping)\n * → boundary-aware truncation\n * → per-surface empty-text default\n *\n * Surfaces choose *policy* (send a sanitized fallback vs skip entirely) via\n * `allowFallback`; they no longer choose (or forget) sanitization steps.\n *\n * See `.pi/skills/review-opportunity-presentation/SKILL.md` for the review\n * checklist this module exists to satisfy.\n */\n\nimport { truncateAtBoundary, viewerCentricCardSummary } from \"./opportunity.presentation.js\";\nimport { stripUnsupportedOpportunityClaims } from \"./opportunity.claim-safety.js\";\n\n/** Default max length for fallback summaries (matches presenter internal fallback). */\nexport const SAFE_FALLBACK_MAX_CHARS = 300;\n\n/** Default copy when no reasoning text is available at all. */\nexport const DEFAULT_EMPTY_FALLBACK_TEXT = \"A promising connection.\";\n\n/** Default headline for fallback presentations (matches presenter internal fallback). */\nexport const DEFAULT_FALLBACK_HEADLINE = \"A promising connection\";\n\n/** Default CTA for fallback presentations (matches presenter internal fallback). */\nexport const DEFAULT_FALLBACK_ACTION =\n \"Take a look and decide whether to reach out.\";\n\nexport interface SafeFallbackOptions {\n /** Display name of the counterpart shown on the card (enables viewer-centric rewrite). */\n counterpartName?: string;\n /** Display name of the viewer; sentences describing the viewer are skipped/rewritten to \"you\". */\n viewerName?: string;\n /** Introducer display name; introducer mentions are stripped from the summary body. */\n introducerName?: string | null;\n /** Max output length (boundary-aware). Default {@link SAFE_FALLBACK_MAX_CHARS}. */\n maxChars?: number;\n /** Copy returned when reasoning is empty/blank. Default {@link DEFAULT_EMPTY_FALLBACK_TEXT}. */\n emptyText?: string;\n}\n\n/**\n * Produce safe user-facing fallback copy from raw match reasoning.\n *\n * This is the ONE sanitization standard: UUID stripping, introducer-mention\n * stripping, and viewer-centric rewrite (via {@link viewerCentricCardSummary}),\n * followed by whitespace normalization and boundary-aware truncation (via\n * {@link truncateAtBoundary}). Never returns raw reasoning verbatim beyond\n * these guarantees, and never returns an empty string.\n *\n * @param rawReasoning - Raw `interpretation.reasoning` / `matchReason` text (may be null/undefined).\n * @param opts - Per-surface knobs (names for rewrite, max length, empty-text copy).\n */\nexport function safeFallbackSummary(\n rawReasoning: string | null | undefined,\n opts: SafeFallbackOptions = {},\n): string {\n const emptyText = opts.emptyText ?? DEFAULT_EMPTY_FALLBACK_TEXT;\n const maxChars = opts.maxChars ?? SAFE_FALLBACK_MAX_CHARS;\n\n const normalized = (rawReasoning ?? \"\").replace(/\\s+/g, \" \").trim();\n if (!normalized) return emptyText;\n const claimSafeInput = stripUnsupportedOpportunityClaims(normalized);\n if (!claimSafeInput) return emptyText;\n\n // viewerCentricCardSummary handles UUID stripping, introducer-mention\n // stripping, and the viewer-centric rewrite. Pass Infinity so truncation is\n // handled by boundary-aware logic below instead of a mid-word hard slice.\n const rewritten = viewerCentricCardSummary(\n claimSafeInput,\n opts.counterpartName ?? \"\",\n Number.POSITIVE_INFINITY,\n opts.viewerName,\n opts.introducerName ?? undefined,\n );\n\n // Claim validation intentionally runs after viewer-centric rewriting: rewrite\n // heuristics may select or join different source sentences, and the final\n // user-facing sentence set is what must be safe.\n const claimSafe = stripUnsupportedOpportunityClaims(rewritten);\n const truncated = truncateAtBoundary(claimSafe, maxChars);\n return truncated || emptyText;\n}\n\n/** Minimal presenter-output shape the primitive inspects (subset of HomeCardPresentationResult). */\nexport interface SafePresentationCandidate {\n headline?: string;\n personalizedSummary?: string;\n suggestedAction?: string;\n /** Set by OpportunityPresenter when its LLM call failed and it returned fallback-shaped copy. */\n isFallback?: boolean;\n}\n\n/** Opportunity-ish source object accepted by {@link getSafePresentationOrSkip}. */\nexport interface SafePresentationSource {\n /** Presenter output attached to the record, when available. */\n homeCardPresentation?: SafePresentationCandidate | null;\n /** Pre-truncated raw reasoning carried on discovery/list card data. */\n matchReason?: string | null;\n /** Full opportunity interpretation, when the caller holds the record. */\n interpretation?: { reasoning?: string | null } | null;\n}\n\nexport interface SafePresentationOptions extends SafeFallbackOptions {\n /**\n * Policy switch: when false, return null instead of fallback copy so the\n * surface can skip rendering entirely (e.g. scheduled digests where sending\n * degraded copy is worse than sending nothing). Default true.\n */\n allowFallback?: boolean;\n}\n\n/** Resolved safe presentation for a surface to render. */\nexport interface SafePresentation {\n headline: string;\n summary: string;\n suggestedAction: string;\n /** True when copy was derived from raw reasoning rather than genuine LLM presenter output. */\n isFallback: boolean;\n}\n\n/**\n * Resolve the safe user-facing presentation for an opportunity, or signal skip.\n *\n * Resolution order:\n * 1. Genuine presenter output (`homeCardPresentation` present, non-empty, and\n * NOT tagged `isFallback` by the presenter) — claim-validated before return.\n * 2. Otherwise, if `allowFallback` (default true): sanitized fallback copy\n * built from `matchReason` / `interpretation.reasoning` via\n * {@link safeFallbackSummary}.\n * 3. Otherwise `null` — the surface must skip this opportunity.\n *\n * Raw `interpretation.reasoning` / `matchReason` never reaches the caller\n * unsanitized through this function.\n */\nexport function getSafePresentationOrSkip(\n source: SafePresentationSource,\n opts: SafePresentationOptions = {},\n): SafePresentation | null {\n const candidate = source.homeCardPresentation;\n if (candidate?.personalizedSummary?.trim() && !candidate.isFallback) {\n const summary = stripUnsupportedOpportunityClaims(candidate.personalizedSummary);\n if (summary) {\n return {\n headline:\n stripUnsupportedOpportunityClaims(candidate.headline) ||\n DEFAULT_FALLBACK_HEADLINE,\n summary,\n suggestedAction:\n stripUnsupportedOpportunityClaims(candidate.suggestedAction) ||\n DEFAULT_FALLBACK_ACTION,\n isFallback: false,\n };\n }\n }\n\n if (opts.allowFallback === false) return null;\n\n const rawReasoning =\n source.matchReason ?? source.interpretation?.reasoning ?? \"\";\n return {\n headline: DEFAULT_FALLBACK_HEADLINE,\n summary: safeFallbackSummary(rawReasoning, opts),\n suggestedAction: DEFAULT_FALLBACK_ACTION,\n isFallback: true,\n };\n}\n"]}
|
|
@@ -100,6 +100,15 @@ export interface EvaluatedOpportunity {
|
|
|
100
100
|
reasoning: string;
|
|
101
101
|
evidence?: OpportunityEvidence[];
|
|
102
102
|
}
|
|
103
|
+
export interface OpportunityPersistenceOutcome {
|
|
104
|
+
evaluatedCount: number;
|
|
105
|
+
createdCount: number;
|
|
106
|
+
reactivatedCount: number;
|
|
107
|
+
sameTriggerDuplicateSuppressions: number;
|
|
108
|
+
pairActiveNegotiationSuppressions: number;
|
|
109
|
+
crossTriggerAllowedCount: number;
|
|
110
|
+
finalAtomicConflictCount: number;
|
|
111
|
+
}
|
|
103
112
|
/**
|
|
104
113
|
* Which flow triggered this graph invocation. Determines initial persist status,
|
|
105
114
|
* park-window timeout, streaming behavior, and whether AbortSignal is honored.
|
|
@@ -318,17 +327,25 @@ export declare const OpportunityGraphState: import("@langchain/langgraph").Annot
|
|
|
318
327
|
networkId: Id<"networks">;
|
|
319
328
|
existingOpportunityId?: Id<"opportunities">;
|
|
320
329
|
existingStatus?: OpportunityStatus;
|
|
330
|
+
reason?: "same_trigger_recent_duplicate" | "pair_active_negotiation" | "final_atomic_conflict";
|
|
331
|
+
existingTriggerIntentId?: string;
|
|
321
332
|
}[], {
|
|
322
333
|
candidateUserId: Id<"users">;
|
|
323
334
|
networkId: Id<"networks">;
|
|
324
335
|
existingOpportunityId?: Id<"opportunities">;
|
|
325
336
|
existingStatus?: OpportunityStatus;
|
|
337
|
+
reason?: "same_trigger_recent_duplicate" | "pair_active_negotiation" | "final_atomic_conflict";
|
|
338
|
+
existingTriggerIntentId?: string;
|
|
326
339
|
}[] | import("@langchain/langgraph").OverwriteValue<{
|
|
327
340
|
candidateUserId: Id<"users">;
|
|
328
341
|
networkId: Id<"networks">;
|
|
329
342
|
existingOpportunityId?: Id<"opportunities">;
|
|
330
343
|
existingStatus?: OpportunityStatus;
|
|
344
|
+
reason?: "same_trigger_recent_duplicate" | "pair_active_negotiation" | "final_atomic_conflict";
|
|
345
|
+
existingTriggerIntentId?: string;
|
|
331
346
|
}[]>, unknown>;
|
|
347
|
+
/** Typed persist-node counts used by queue telemetry. */
|
|
348
|
+
persistenceOutcome: import("@langchain/langgraph").BaseChannel<OpportunityPersistenceOutcome | undefined, OpportunityPersistenceOutcome | import("@langchain/langgraph").OverwriteValue<OpportunityPersistenceOutcome | undefined> | undefined, unknown>;
|
|
332
349
|
/** Error message if any step fails */
|
|
333
350
|
error: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
334
351
|
/** Output for read mode: enriched list of opportunities. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity.state.d.ts","sourceRoot":"/","sources":["opportunity/opportunity.state.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"opportunity.state.d.ts","sourceRoot":"/","sources":["opportunity/opportunity.state.ts"],"names":[],"mappings":"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"}
|
|
@@ -248,6 +248,11 @@ export const OpportunityGraphState = Annotation.Root({
|
|
|
248
248
|
reducer: (curr, next) => next ?? curr,
|
|
249
249
|
default: () => [],
|
|
250
250
|
}),
|
|
251
|
+
/** Typed persist-node counts used by queue telemetry. */
|
|
252
|
+
persistenceOutcome: Annotation({
|
|
253
|
+
reducer: (curr, next) => next ?? curr,
|
|
254
|
+
default: () => undefined,
|
|
255
|
+
}),
|
|
251
256
|
/** Error message if any step fails */
|
|
252
257
|
error: Annotation({
|
|
253
258
|
reducer: (curr, next) => next,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity.state.js","sourceRoot":"/","sources":["opportunity/opportunity.state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA6HlD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAA2B,EAC3B,QAAuC;IAEvC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC5C,OAAO,OAAO,KAAK,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;AAChE,CAAC;AA+BD;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAC,IAAI,CAAC;IACnD,kCAAkC;IAClC,MAAM,EAAE,UAAU,CAAc;QAC9B,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAiB;KACjC,CAAC;IAEF,WAAW,EAAE,UAAU,CAAqB;QAC1C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,SAAS,EAAE,UAAU,CAA6B;QAChD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF;;;;;;OAMG;IACH,UAAU,EAAE,UAAU,CAA+B;QACnD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,mIAAmI;IACnI,eAAe,EAAE,UAAU,CAA4B;QACrD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,sFAAsF;IACtF,YAAY,EAAE,UAAU,CAA0B;QAChD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,uJAAuJ;IACvJ,gBAAgB,EAAE,UAAU,CAA0B;QACpD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,OAAO,EAAE,UAAU,CAA0B;QAC3C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;KACpB,CAAC;IAEF;;;;;;;;;OASG;IACH,OAAO,EAAE,UAAU,CAAqB;QACtC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF;;;;;;;;;OASG;IACH,oBAAoB,EAAE,UAAU,CAG5B;QACF,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF;;;;;;;;;;;;;;;OAeG;IACH,aAAa,EAAE,UAAU,CAAkJ;QACzK,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAiB;KACjC,CAAC;IAEF,+EAA+E;IAC/E,oBAAoB,EAAE,UAAU,CAAoB;QAClD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,4DAA4D;IAC5D,gBAAgB,EAAE,UAAU,CAAqB;QAC/C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,6DAA6D;IAC7D,iBAAiB,EAAE,UAAU,CAA6B;QACxD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,+FAA+F;IAC/F,mBAAmB,EAAE,UAAU,CAAyC;QACtE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,0DAA0D;IAC1D,aAAa,EAAE,UAAU,CAAqB;QAC5C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,gEAAgE;IAChE,SAAS,EAAE,UAAU,CAAqB;QACxC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,4CAA4C;IAE5C,6DAA6D;IAC7D,cAAc,EAAE,UAAU,CAAkB;QAC1C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,6CAA6C;IAC7C,YAAY,EAAE,UAAU,CAAmB;QACzC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,mDAAmD;IACnD,cAAc,EAAE,UAAU,CAAkB;QAC1C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,wIAAwI;IACxI,oBAAoB,EAAE,UAAU,CAAyB;QACvD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;KACpB,CAAC;IAEF,yJAAyJ;IACzJ,eAAe,EAAE,UAAU,CAAuB;QAChD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ;KACxB,CAAC;IAEF,mHAAmH;IACnH,uBAAuB,EAAE,UAAU,CAA4B;QAC7D,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,wFAAwF;IACxF,aAAa,EAAE,UAAU,CAA2B;QAClD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI;KACpB,CAAC;IAEF,wGAAwG;IACxG,cAAc,EAAE,UAAU,CAA4D;QACpF,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,6FAA6F;IAC7F,cAAc,EAAE,UAAU,CAA6F;QACrH,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,qEAAqE;IACrE,qBAAqB,EAAE,UAAU,CAAU;QACzC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK;KACrB,CAAC;IAEF,sHAAsH;IACtH,qBAAqB,EAAE,UAAU,CAAU;QACzC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK;KACrB,CAAC;IAEF,kFAAkF;IAClF,0BAA0B,EAAE,UAAU,CAAqB;QACzD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,sDAAsD;IACtD,cAAc,EAAE,UAAU,CAA2B;QACnD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;KACpB,CAAC;IAEF,8DAA8D;IAC9D,UAAU,EAAE,UAAU,CAAmB;QACvC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,kFAAkF;IAClF,mBAAmB,EAAE,UAAU,CAAmB;QAChD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,qEAAqE;IACrE,WAAW,EAAE,UAAU,CAAgB;QACrC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI;KACpB,CAAC;IAEF,iEAAiE;IACjE,mBAAmB,EAAE,UAAU,CAAuB;QACpD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,yEAAyE;IACzE,sBAAsB,EAAE,UAAU,CAAyB;QACzD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,6CAA6C;IAE7C,+CAA+C;IAC/C,aAAa,EAAE,UAAU,CAAgB;QACvC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,+HAA+H;IAC/H,qBAAqB,EAAE,UAAU,CAK7B;QACF,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,sCAAsC;IACtC,KAAK,EAAE,UAAU,CAAqB;QACpC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,4DAA4D;IAC5D,UAAU,EAAE,UAAU,CAcP;QACb,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,2CAA2C;IAC3C,cAAc,EAAE,UAAU,CAOX;QACb,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,uBAAuB;IAEvB;;;;OAIG;IACH,KAAK,EAAE,UAAU,CAA2E;QAC1F,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACnD,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,sEAAsE;IACtE,YAAY,EAAE,UAAU,CAAmB;QACzC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC;QACvC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF;;;;;;;;OAQG;IACH,qBAAqB,EAAE,UAAU,CAAyB;QACxD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACnD,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,sFAAsF;IACtF,gBAAgB,EAAE,UAAU,CAA0B;QACpD,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACtC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI;KACpB,CAAC;CACH,CAAC,CAAC","sourcesContent":["import { Annotation } from \"@langchain/langgraph\";\nimport type { Id } from '../shared/interfaces/database.interface.js';\nimport type { OpportunityStatus, Opportunity } from '../shared/interfaces/database.interface.js';\nimport type { Lens } from '../shared/interfaces/embedder.interface.js';\nimport type { EvaluatorEntity } from './opportunity.evaluator.js';\nimport type { DebugMetaAgent } from '../chat/chat-streaming.types.js';\nimport type { OpportunityEvidence } from '../shared/schemas/network-assignment.schema.js';\nimport type { DiscoveryNegotiation, DiscoverySummary } from \"../shared/schemas/discovery-question.schema.js\";\n\n/**\n * Opportunity Graph State (Linear Multi-Step Workflow)\n *\n * Flow: Prep → Scope → Discovery → Evaluation → Ranking → Persist → END\n *\n * Following the intent graph pattern with Annotation-based state management.\n */\n\n/** Asker's profile shape (identity + context). Used by sourceProfile annotation. */\nexport interface SourceProfileData {\n identity?: { name?: string; bio?: string; location?: string };\n context?: string;\n}\n\n/**\n * Indexed intent with hyde document (from prep node)\n */\nexport interface IndexedIntent {\n intentId: Id<'intents'>;\n payload: string;\n summary?: string;\n hydeDocumentId?: string;\n hydeEmbedding?: number[];\n indexes: Id<'networks'>[];\n}\n\n/**\n * Target index for search (from scope node)\n */\nexport interface TargetNetwork {\n networkId: Id<'networks'>;\n title: string;\n memberCount: number;\n}\n\n/**\n * Candidate match from discovery (semantic search).\n */\nexport interface CandidateMatch {\n candidateUserId: Id<'users'>;\n candidateIntentId?: Id<'intents'>;\n /** Source premise that produced this candidate (set when discoverySource is 'premise-similarity'). */\n sourcePremiseId?: Id<'premises'>;\n /** Candidate premise that matched this candidate (set for premise-based matches). */\n candidatePremiseId?: Id<'premises'>;\n /** Source context that produced this candidate (set when discoverySource is 'context-to-intent'). */\n sourceContextId?: string;\n networkId: Id<'networks'>;\n similarity: number;\n /** Free-text lens label that produced this match. */\n lens: string;\n candidatePayload: string;\n candidateSummary?: string;\n /** How this candidate was found: 'query' (HyDE from search text), 'premise-similarity', or 'context-to-intent'. */\n discoverySource?: 'query' | 'premise-similarity' | 'context-to-intent';\n /** Which discovery strategies found this candidate (set by mergeStrategyCandidates). */\n matchedStrategies?: string[];\n /** Typed evidence that explains why this candidate entered evaluation. */\n evidence?: OpportunityEvidence[];\n}\n\n/**\n * Evaluated candidate with LLM scoring (legacy; used when evaluator returns source/candidate pair).\n * candidateIntentId is set for intent matches; omitted for profile-only matches.\n */\nexport interface EvaluatedCandidate {\n sourceUserId: Id<'users'>;\n candidateUserId: Id<'users'>;\n sourceIntentId?: Id<'intents'>;\n candidateIntentId?: Id<'intents'>;\n networkId: Id<'networks'>;\n score: number; // 0-100\n reasoning: string; // Third-party analytical explanation of the match (for LLM agents)\n valencyRole: 'Agent' | 'Patient' | 'Peer';\n /** Free-text lens label that produced this match. */\n lens: string;\n}\n\n/**\n * Actor in an evaluated opportunity (from entity-bundle evaluator).\n * networkId is filled from the entity bundle in the graph, not by the evaluator.\n */\nexport interface EvaluatedOpportunityActor {\n userId: Id<'users'>;\n role: 'agent' | 'patient' | 'peer';\n intentId?: Id<'intents'>;\n networkId: Id<'networks'>;\n}\n\n/**\n * Evaluated opportunity with multi-actor output (entity-bundle evaluator).\n */\nexport interface EvaluatedOpportunity {\n actors: EvaluatedOpportunityActor[];\n score: number;\n reasoning: string;\n evidence?: OpportunityEvidence[];\n}\n\n/**\n * Which flow triggered this graph invocation. Determines initial persist status,\n * park-window timeout, streaming behavior, and whether AbortSignal is honored.\n *\n * - 'ambient' (default): queue-driven. Persists at the trigger default of\n * `pending` unless `options.initialStatus` overrides (the queue worker\n * passes `'latent'`, chat-bound ambient discovery passes `'draft'`). 5-min\n * park window, no streaming, ignores abort.\n * - 'orchestrator': chat-driven. Persists at the trigger default of\n * `negotiating` unless `options.initialStatus` overrides. 60s park window,\n * streams `opportunity_draft_ready` events, honors abort.\n *\n * See {@link resolveInitialStatus} for the exact fallback used when\n * `options.initialStatus` is undefined.\n */\nexport type OpportunityTrigger = 'ambient' | 'orchestrator';\n\n/**\n * Resolves the initial status for opportunities created in the persist node.\n *\n * Explicit `options.initialStatus` always wins (callers like the chat tool or\n * maintenance scripts override per-call). When the caller leaves it\n * undefined, the trigger drives the default:\n * - 'orchestrator' → 'negotiating' (chat-driven; negotiations run before the\n * user sees a draft card).\n * - 'ambient' (or any other trigger) → 'pending' (long-standing default for\n * queue- and intent-driven discovery).\n *\n * Lives here rather than in opportunity.graph.ts so unit tests can exercise\n * it without pulling in the full graph (and the evaluator's LLM requirements).\n *\n * @param trigger - The graph invocation's trigger\n * @param explicit - Caller-supplied initial status from options.initialStatus\n */\nexport function resolveInitialStatus(\n trigger: OpportunityTrigger,\n explicit: OpportunityStatus | undefined,\n): OpportunityStatus {\n if (explicit !== undefined) return explicit;\n return trigger === 'orchestrator' ? 'negotiating' : 'pending';\n}\n\n/**\n * Options passed to the graph\n */\nexport interface OpportunityGraphOptions {\n /** Initial status for created opportunities (default: 'pending') */\n initialStatus?: OpportunityStatus;\n /** Minimum score threshold (default: 50) */\n minScore?: number;\n /** Maximum opportunities to return (default: 20) */\n limit?: number;\n /** Pre-inferred lenses (if not provided, lens inference runs automatically in HyDE graph) */\n lenses?: Lens[];\n /** User's search query for HyDE generation */\n hydeDescription?: string;\n /** Existing opportunities summary for evaluator deduplication */\n existingOpportunities?: string;\n /** Chat session ID for draft opportunities; stored as context.conversationId for visibility filtering. */\n conversationId?: string;\n /**\n * MCP-only: cap the negotiate-phase wall-clock at this many milliseconds.\n * When set, `negotiateNode` races `negotiateCandidates(...)` against a timer;\n * if the timer wins, the node returns early with a `timed_out` trace and the\n * unawaited negotiation chains finalize each opp's DB status in the\n * background. Set to 20_000 by the MCP `discover_opportunities` handler.\n * Chat, ambient queue, and all other callers omit this — existing behavior.\n */\n negotiateTimeoutMs?: number;\n}\n\n/**\n * Opportunity Graph State Annotation\n */\nexport const OpportunityGraphState = Annotation.Root({\n // ─── Input Fields (Required) ───\n userId: Annotation<Id<'users'>>({\n reducer: (curr, next) => next ?? curr,\n default: () => '' as Id<'users'>,\n }),\n\n searchQuery: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n networkId: Annotation<Id<'networks'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /**\n * Optional set of indexes discovery may search within (e.g. a network-scoped\n * agent's reachable networks: the bound network plus the user's personal network).\n * The scope node intersects this with the user's actual memberships. Ignored\n * when `networkId` is set (single-network override). When unset, discovery\n * spans all of the user's networks.\n */\n indexScope: Annotation<Id<'networks'>[] | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Optional intent to use as discovery source and for triggeredBy. When set, used for search text (if query empty) and persist. */\n triggerIntentId: Annotation<Id<'intents'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Optional: restrict discovery to this specific user ID only (direct connection). */\n targetUserId: Annotation<Id<'users'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Optional: discover on behalf of this user (introducer flow). When set, prep/eval use this user's profile/intents; userId becomes the introducer. */\n onBehalfOfUserId: Annotation<Id<'users'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n options: Annotation<OpportunityGraphOptions>({\n reducer: (curr, next) => next ?? curr,\n default: () => ({}),\n }),\n\n /**\n * Which flow triggered this graph invocation. See {@link OpportunityTrigger}\n * for the exact branch behavior and {@link resolveInitialStatus} for the\n * persist default when `options.initialStatus` is unset.\n *\n * - 'ambient' (default): queue-driven, persist default `pending`, 5-min\n * park window, no streaming, ignores abort.\n * - 'orchestrator': chat-driven, persist default `negotiating`, 60s park\n * window, streams `opportunity_draft_ready` events, honors abort.\n */\n trigger: Annotation<OpportunityTrigger>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'ambient',\n }),\n\n /**\n * Accepted opportunities the persist node discovered between the discoverer\n * and a candidate actor (same pair, status='accepted'). The orchestrator\n * branch populates this so the discover_opportunities tool (Task 7) can tell\n * the LLM \"these pairs are already connected, surface the existing chat\n * rather than creating a new draft\". Always empty for the ambient trigger.\n *\n * Left intentionally minimal — conversationId/URL resolution happens at\n * Start Chat time (Task 8), not here.\n */\n dedupAlreadyAccepted: Annotation<Array<{\n opportunityId: string;\n counterpartyUserId: string;\n }>>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /**\n * Operation mode controls graph flow:\n * - 'create': Existing discover pipeline (Prep → Scope → Discovery → Evaluation → Ranking → Persist)\n * - 'create_introduction': Introduction path (validation → evaluation → persist) for chat-driven intros\n * - 'continue_discovery': Pagination path (Prep → Evaluation → Ranking → Persist) using pre-loaded candidates\n * - 'read': List opportunities filtered by userId and optionally networkId (fast path)\n * - 'update': Change opportunity status (accept, reject, etc.)\n * - 'delete': Expire/archive an opportunity\n * - 'send': Promote latent opportunity to pending + queue notification\n * - 'negotiate_existing': Load an existing opportunity by opportunityId and run bilateral negotiation.\n * Used after introducer approval to trigger the normal negotiation flow.\n * - 'approve_introduction': Mark the caller as having approved a latent introducer opportunity,\n * then enqueue a negotiate_existing job for that opportunity.\n *\n * Defaults to 'create' for backward compatibility.\n */\n operationMode: Annotation<'create' | 'create_introduction' | 'continue_discovery' | 'read' | 'update' | 'delete' | 'send' | 'negotiate_existing' | 'approve_introduction'>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'create' as const,\n }),\n\n /** Introduction mode: pre-gathered entities (profiles + intents per party). */\n introductionEntities: Annotation<EvaluatorEntity[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Introduction mode: optional hint from the introducer. */\n introductionHint: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** When set (e.g. chat scope), networkId must match this. */\n requiredNetworkId: Annotation<Id<'networks'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Set by intro_evaluation; used by persist to build manual detection and introducer actor. */\n introductionContext: Annotation<{ createdByName?: string } | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Target opportunity ID for update/delete/send modes. */\n opportunityId: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** New status for update mode (e.g. 'accepted', 'rejected'). */\n newStatus: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n // ─── Intermediate Fields (Accumulated) ───\n\n /** User's indexed intents with hyde documents (from prep) */\n indexedIntents: Annotation<IndexedIntent[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** User's network memberships (from prep) */\n userNetworks: Annotation<Id<'networks'>[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Target indexes to search within (from scope) */\n targetNetworks: Annotation<TargetNetwork[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Per-index relevancy scores for dedup tie-breaking. Background path: from intent_indexes. Chat path: transient from IntentIndexer. */\n indexRelevancyScores: Annotation<Record<string, number>>({\n reducer: (curr, next) => next ?? curr,\n default: () => ({}),\n }),\n\n /** Whether discovery used intent (path A) or user context (path B/C). Used by persist for triggeredBy. In-memory routing state only; never persisted. */\n discoverySource: Annotation<'intent' | 'context'>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'intent',\n }),\n\n /** Resolved intent ID used for this discovery run (when discoverySource is 'intent'). Set by intent-resolution. */\n resolvedTriggerIntentId: Annotation<Id<'intents'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Asker's profile (from prep). Used for profile-as-source discovery and evaluation. */\n sourceProfile: Annotation<SourceProfileData | null>({\n reducer: (curr, next) => next ?? curr,\n default: () => null,\n }),\n\n /** User's active premises with embeddings (from prep). Used for premise-to-premise discovery path D. */\n sourcePremises: Annotation<Array<{ premiseId: Id<'premises'>; embedding: number[] }>>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** User context embeddings per network (from prep). Used for context-to-intent discovery. */\n sourceContexts: Annotation<Array<{ contextId: string; networkId: Id<'networks'>; text: string; embedding: number[] }>>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Resolved intent is in at least one target index (path A vs C). */\n resolvedIntentInIndex: Annotation<boolean>({\n reducer: (curr, next) => next ?? curr,\n default: () => false,\n }),\n\n /** Create-intent signal: when true, tool should return createIntentSuggested so agent can auto-call create_intent. */\n createIntentSuggested: Annotation<boolean>({\n reducer: (curr, next) => next ?? curr,\n default: () => false,\n }),\n\n /** Suggested description for create_intent when createIntentSuggested is true. */\n suggestedIntentDescription: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** HyDE embeddings per lens label (from discovery) */\n hydeEmbeddings: Annotation<Record<string, number[]>>({\n reducer: (curr, next) => next ?? curr,\n default: () => ({}),\n }),\n\n /** Candidate matches from semantic search (from discovery) */\n candidates: Annotation<CandidateMatch[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Candidates not yet evaluated (for pagination -- cached in Redis by caller). */\n remainingCandidates: Annotation<CandidateMatch[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Discovery session ID for pagination (maps to Redis cache key). */\n discoveryId: Annotation<string | null>({\n reducer: (curr, next) => next ?? curr,\n default: () => null,\n }),\n\n /** Evaluated candidates with scores (from evaluation; legacy) */\n evaluatedCandidates: Annotation<EvaluatedCandidate[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Evaluated opportunities with actors (from entity-bundle evaluator) */\n evaluatedOpportunities: Annotation<EvaluatedOpportunity[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n // ─── Output Fields (Overwrite per turn) ───\n\n /** Final ranked and persisted opportunities */\n opportunities: Annotation<Opportunity[]>({\n reducer: (curr, next) => next,\n default: () => [],\n }),\n\n /** Discovery path: pairs skipped because an opportunity already exists between viewer and candidate (no duplicate created). */\n existingBetweenActors: Annotation<Array<{\n candidateUserId: Id<'users'>;\n networkId: Id<'networks'>;\n existingOpportunityId?: Id<'opportunities'>;\n existingStatus?: OpportunityStatus;\n }>>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Error message if any step fails */\n error: Annotation<string | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n /** Output for read mode: enriched list of opportunities. */\n readResult: Annotation<{\n count: number;\n message?: string;\n opportunities: Array<{\n id: string;\n indexName: string;\n connectedWith: string[];\n suggestedBy: string | null;\n reasoning: string;\n status: string;\n category: string;\n confidence: number | null;\n source: string | null;\n }>;\n } | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n /** Output for update/delete/send modes. */\n mutationResult: Annotation<{\n success: boolean;\n message?: string;\n opportunityId?: string;\n notified?: string[];\n conversationId?: string;\n error?: string;\n } | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n // ─── Trace Output ───\n\n /**\n * Accumulated trace entries from each graph node.\n * Used for observability: surfaces internal processing steps (search query, HyDE strategies,\n * candidates found, evaluation results) to the frontend.\n */\n trace: Annotation<Array<{ node: string; detail?: string; data?: Record<string, unknown> }>>({\n reducer: (curr, next) => [...curr, ...(next || [])],\n default: () => [],\n }),\n\n /** Timing records for each agent invocation within this graph run. */\n agentTimings: Annotation<DebugMetaAgent[]>({\n reducer: (acc, val) => [...acc, ...val],\n default: () => [],\n }),\n\n /**\n * Per-candidate negotiation records captured by `negotiateNode`. Populated\n * regardless of accept/reject so the question generator sees a complete\n * picture. Populated for ALL triggers (ambient + orchestrator) since the\n * negotiate node's `onCandidateResolved` hook is unconditional; only the\n * orchestrator streaming side-effects (opportunity_draft_ready emission)\n * are trigger-gated. Empty when the negotiate node was skipped (no\n * opportunities to negotiate).\n */\n discoveryNegotiations: Annotation<DiscoveryNegotiation[]>({\n reducer: (curr, next) => [...curr, ...(next || [])],\n default: () => [],\n }),\n\n /** Aggregate counters across `discoveryNegotiations`. Built in the negotiate node. */\n discoverySummary: Annotation<DiscoverySummary | null>({\n reducer: (_curr, next) => next ?? null,\n default: () => null,\n }),\n});\n"]}
|
|
1
|
+
{"version":3,"file":"opportunity.state.js","sourceRoot":"/","sources":["opportunity/opportunity.state.ts"],"names":[],"mappings":"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","sourcesContent":["import { Annotation } from \"@langchain/langgraph\";\nimport type { Id } from '../shared/interfaces/database.interface.js';\nimport type { OpportunityStatus, Opportunity } from '../shared/interfaces/database.interface.js';\nimport type { Lens } from '../shared/interfaces/embedder.interface.js';\nimport type { EvaluatorEntity } from './opportunity.evaluator.js';\nimport type { DebugMetaAgent } from '../chat/chat-streaming.types.js';\nimport type { OpportunityEvidence } from '../shared/schemas/network-assignment.schema.js';\nimport type { DiscoveryNegotiation, DiscoverySummary } from \"../shared/schemas/discovery-question.schema.js\";\n\n/**\n * Opportunity Graph State (Linear Multi-Step Workflow)\n *\n * Flow: Prep → Scope → Discovery → Evaluation → Ranking → Persist → END\n *\n * Following the intent graph pattern with Annotation-based state management.\n */\n\n/** Asker's profile shape (identity + context). Used by sourceProfile annotation. */\nexport interface SourceProfileData {\n identity?: { name?: string; bio?: string; location?: string };\n context?: string;\n}\n\n/**\n * Indexed intent with hyde document (from prep node)\n */\nexport interface IndexedIntent {\n intentId: Id<'intents'>;\n payload: string;\n summary?: string;\n hydeDocumentId?: string;\n hydeEmbedding?: number[];\n indexes: Id<'networks'>[];\n}\n\n/**\n * Target index for search (from scope node)\n */\nexport interface TargetNetwork {\n networkId: Id<'networks'>;\n title: string;\n memberCount: number;\n}\n\n/**\n * Candidate match from discovery (semantic search).\n */\nexport interface CandidateMatch {\n candidateUserId: Id<'users'>;\n candidateIntentId?: Id<'intents'>;\n /** Source premise that produced this candidate (set when discoverySource is 'premise-similarity'). */\n sourcePremiseId?: Id<'premises'>;\n /** Candidate premise that matched this candidate (set for premise-based matches). */\n candidatePremiseId?: Id<'premises'>;\n /** Source context that produced this candidate (set when discoverySource is 'context-to-intent'). */\n sourceContextId?: string;\n networkId: Id<'networks'>;\n similarity: number;\n /** Free-text lens label that produced this match. */\n lens: string;\n candidatePayload: string;\n candidateSummary?: string;\n /** How this candidate was found: 'query' (HyDE from search text), 'premise-similarity', or 'context-to-intent'. */\n discoverySource?: 'query' | 'premise-similarity' | 'context-to-intent';\n /** Which discovery strategies found this candidate (set by mergeStrategyCandidates). */\n matchedStrategies?: string[];\n /** Typed evidence that explains why this candidate entered evaluation. */\n evidence?: OpportunityEvidence[];\n}\n\n/**\n * Evaluated candidate with LLM scoring (legacy; used when evaluator returns source/candidate pair).\n * candidateIntentId is set for intent matches; omitted for profile-only matches.\n */\nexport interface EvaluatedCandidate {\n sourceUserId: Id<'users'>;\n candidateUserId: Id<'users'>;\n sourceIntentId?: Id<'intents'>;\n candidateIntentId?: Id<'intents'>;\n networkId: Id<'networks'>;\n score: number; // 0-100\n reasoning: string; // Third-party analytical explanation of the match (for LLM agents)\n valencyRole: 'Agent' | 'Patient' | 'Peer';\n /** Free-text lens label that produced this match. */\n lens: string;\n}\n\n/**\n * Actor in an evaluated opportunity (from entity-bundle evaluator).\n * networkId is filled from the entity bundle in the graph, not by the evaluator.\n */\nexport interface EvaluatedOpportunityActor {\n userId: Id<'users'>;\n role: 'agent' | 'patient' | 'peer';\n intentId?: Id<'intents'>;\n networkId: Id<'networks'>;\n}\n\n/**\n * Evaluated opportunity with multi-actor output (entity-bundle evaluator).\n */\nexport interface EvaluatedOpportunity {\n actors: EvaluatedOpportunityActor[];\n score: number;\n reasoning: string;\n evidence?: OpportunityEvidence[];\n}\n\nexport interface OpportunityPersistenceOutcome {\n evaluatedCount: number;\n createdCount: number;\n reactivatedCount: number;\n sameTriggerDuplicateSuppressions: number;\n pairActiveNegotiationSuppressions: number;\n crossTriggerAllowedCount: number;\n finalAtomicConflictCount: number;\n}\n\n/**\n * Which flow triggered this graph invocation. Determines initial persist status,\n * park-window timeout, streaming behavior, and whether AbortSignal is honored.\n *\n * - 'ambient' (default): queue-driven. Persists at the trigger default of\n * `pending` unless `options.initialStatus` overrides (the queue worker\n * passes `'latent'`, chat-bound ambient discovery passes `'draft'`). 5-min\n * park window, no streaming, ignores abort.\n * - 'orchestrator': chat-driven. Persists at the trigger default of\n * `negotiating` unless `options.initialStatus` overrides. 60s park window,\n * streams `opportunity_draft_ready` events, honors abort.\n *\n * See {@link resolveInitialStatus} for the exact fallback used when\n * `options.initialStatus` is undefined.\n */\nexport type OpportunityTrigger = 'ambient' | 'orchestrator';\n\n/**\n * Resolves the initial status for opportunities created in the persist node.\n *\n * Explicit `options.initialStatus` always wins (callers like the chat tool or\n * maintenance scripts override per-call). When the caller leaves it\n * undefined, the trigger drives the default:\n * - 'orchestrator' → 'negotiating' (chat-driven; negotiations run before the\n * user sees a draft card).\n * - 'ambient' (or any other trigger) → 'pending' (long-standing default for\n * queue- and intent-driven discovery).\n *\n * Lives here rather than in opportunity.graph.ts so unit tests can exercise\n * it without pulling in the full graph (and the evaluator's LLM requirements).\n *\n * @param trigger - The graph invocation's trigger\n * @param explicit - Caller-supplied initial status from options.initialStatus\n */\nexport function resolveInitialStatus(\n trigger: OpportunityTrigger,\n explicit: OpportunityStatus | undefined,\n): OpportunityStatus {\n if (explicit !== undefined) return explicit;\n return trigger === 'orchestrator' ? 'negotiating' : 'pending';\n}\n\n/**\n * Options passed to the graph\n */\nexport interface OpportunityGraphOptions {\n /** Initial status for created opportunities (default: 'pending') */\n initialStatus?: OpportunityStatus;\n /** Minimum score threshold (default: 50) */\n minScore?: number;\n /** Maximum opportunities to return (default: 20) */\n limit?: number;\n /** Pre-inferred lenses (if not provided, lens inference runs automatically in HyDE graph) */\n lenses?: Lens[];\n /** User's search query for HyDE generation */\n hydeDescription?: string;\n /** Existing opportunities summary for evaluator deduplication */\n existingOpportunities?: string;\n /** Chat session ID for draft opportunities; stored as context.conversationId for visibility filtering. */\n conversationId?: string;\n /**\n * MCP-only: cap the negotiate-phase wall-clock at this many milliseconds.\n * When set, `negotiateNode` races `negotiateCandidates(...)` against a timer;\n * if the timer wins, the node returns early with a `timed_out` trace and the\n * unawaited negotiation chains finalize each opp's DB status in the\n * background. Set to 20_000 by the MCP `discover_opportunities` handler.\n * Chat, ambient queue, and all other callers omit this — existing behavior.\n */\n negotiateTimeoutMs?: number;\n}\n\n/**\n * Opportunity Graph State Annotation\n */\nexport const OpportunityGraphState = Annotation.Root({\n // ─── Input Fields (Required) ───\n userId: Annotation<Id<'users'>>({\n reducer: (curr, next) => next ?? curr,\n default: () => '' as Id<'users'>,\n }),\n\n searchQuery: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n networkId: Annotation<Id<'networks'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /**\n * Optional set of indexes discovery may search within (e.g. a network-scoped\n * agent's reachable networks: the bound network plus the user's personal network).\n * The scope node intersects this with the user's actual memberships. Ignored\n * when `networkId` is set (single-network override). When unset, discovery\n * spans all of the user's networks.\n */\n indexScope: Annotation<Id<'networks'>[] | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Optional intent to use as discovery source and for triggeredBy. When set, used for search text (if query empty) and persist. */\n triggerIntentId: Annotation<Id<'intents'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Optional: restrict discovery to this specific user ID only (direct connection). */\n targetUserId: Annotation<Id<'users'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Optional: discover on behalf of this user (introducer flow). When set, prep/eval use this user's profile/intents; userId becomes the introducer. */\n onBehalfOfUserId: Annotation<Id<'users'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n options: Annotation<OpportunityGraphOptions>({\n reducer: (curr, next) => next ?? curr,\n default: () => ({}),\n }),\n\n /**\n * Which flow triggered this graph invocation. See {@link OpportunityTrigger}\n * for the exact branch behavior and {@link resolveInitialStatus} for the\n * persist default when `options.initialStatus` is unset.\n *\n * - 'ambient' (default): queue-driven, persist default `pending`, 5-min\n * park window, no streaming, ignores abort.\n * - 'orchestrator': chat-driven, persist default `negotiating`, 60s park\n * window, streams `opportunity_draft_ready` events, honors abort.\n */\n trigger: Annotation<OpportunityTrigger>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'ambient',\n }),\n\n /**\n * Accepted opportunities the persist node discovered between the discoverer\n * and a candidate actor (same pair, status='accepted'). The orchestrator\n * branch populates this so the discover_opportunities tool (Task 7) can tell\n * the LLM \"these pairs are already connected, surface the existing chat\n * rather than creating a new draft\". Always empty for the ambient trigger.\n *\n * Left intentionally minimal — conversationId/URL resolution happens at\n * Start Chat time (Task 8), not here.\n */\n dedupAlreadyAccepted: Annotation<Array<{\n opportunityId: string;\n counterpartyUserId: string;\n }>>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /**\n * Operation mode controls graph flow:\n * - 'create': Existing discover pipeline (Prep → Scope → Discovery → Evaluation → Ranking → Persist)\n * - 'create_introduction': Introduction path (validation → evaluation → persist) for chat-driven intros\n * - 'continue_discovery': Pagination path (Prep → Evaluation → Ranking → Persist) using pre-loaded candidates\n * - 'read': List opportunities filtered by userId and optionally networkId (fast path)\n * - 'update': Change opportunity status (accept, reject, etc.)\n * - 'delete': Expire/archive an opportunity\n * - 'send': Promote latent opportunity to pending + queue notification\n * - 'negotiate_existing': Load an existing opportunity by opportunityId and run bilateral negotiation.\n * Used after introducer approval to trigger the normal negotiation flow.\n * - 'approve_introduction': Mark the caller as having approved a latent introducer opportunity,\n * then enqueue a negotiate_existing job for that opportunity.\n *\n * Defaults to 'create' for backward compatibility.\n */\n operationMode: Annotation<'create' | 'create_introduction' | 'continue_discovery' | 'read' | 'update' | 'delete' | 'send' | 'negotiate_existing' | 'approve_introduction'>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'create' as const,\n }),\n\n /** Introduction mode: pre-gathered entities (profiles + intents per party). */\n introductionEntities: Annotation<EvaluatorEntity[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Introduction mode: optional hint from the introducer. */\n introductionHint: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** When set (e.g. chat scope), networkId must match this. */\n requiredNetworkId: Annotation<Id<'networks'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Set by intro_evaluation; used by persist to build manual detection and introducer actor. */\n introductionContext: Annotation<{ createdByName?: string } | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Target opportunity ID for update/delete/send modes. */\n opportunityId: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** New status for update mode (e.g. 'accepted', 'rejected'). */\n newStatus: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n // ─── Intermediate Fields (Accumulated) ───\n\n /** User's indexed intents with hyde documents (from prep) */\n indexedIntents: Annotation<IndexedIntent[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** User's network memberships (from prep) */\n userNetworks: Annotation<Id<'networks'>[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Target indexes to search within (from scope) */\n targetNetworks: Annotation<TargetNetwork[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Per-index relevancy scores for dedup tie-breaking. Background path: from intent_indexes. Chat path: transient from IntentIndexer. */\n indexRelevancyScores: Annotation<Record<string, number>>({\n reducer: (curr, next) => next ?? curr,\n default: () => ({}),\n }),\n\n /** Whether discovery used intent (path A) or user context (path B/C). Used by persist for triggeredBy. In-memory routing state only; never persisted. */\n discoverySource: Annotation<'intent' | 'context'>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'intent',\n }),\n\n /** Resolved intent ID used for this discovery run (when discoverySource is 'intent'). Set by intent-resolution. */\n resolvedTriggerIntentId: Annotation<Id<'intents'> | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Asker's profile (from prep). Used for profile-as-source discovery and evaluation. */\n sourceProfile: Annotation<SourceProfileData | null>({\n reducer: (curr, next) => next ?? curr,\n default: () => null,\n }),\n\n /** User's active premises with embeddings (from prep). Used for premise-to-premise discovery path D. */\n sourcePremises: Annotation<Array<{ premiseId: Id<'premises'>; embedding: number[] }>>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** User context embeddings per network (from prep). Used for context-to-intent discovery. */\n sourceContexts: Annotation<Array<{ contextId: string; networkId: Id<'networks'>; text: string; embedding: number[] }>>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Resolved intent is in at least one target index (path A vs C). */\n resolvedIntentInIndex: Annotation<boolean>({\n reducer: (curr, next) => next ?? curr,\n default: () => false,\n }),\n\n /** Create-intent signal: when true, tool should return createIntentSuggested so agent can auto-call create_intent. */\n createIntentSuggested: Annotation<boolean>({\n reducer: (curr, next) => next ?? curr,\n default: () => false,\n }),\n\n /** Suggested description for create_intent when createIntentSuggested is true. */\n suggestedIntentDescription: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** HyDE embeddings per lens label (from discovery) */\n hydeEmbeddings: Annotation<Record<string, number[]>>({\n reducer: (curr, next) => next ?? curr,\n default: () => ({}),\n }),\n\n /** Candidate matches from semantic search (from discovery) */\n candidates: Annotation<CandidateMatch[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Candidates not yet evaluated (for pagination -- cached in Redis by caller). */\n remainingCandidates: Annotation<CandidateMatch[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Discovery session ID for pagination (maps to Redis cache key). */\n discoveryId: Annotation<string | null>({\n reducer: (curr, next) => next ?? curr,\n default: () => null,\n }),\n\n /** Evaluated candidates with scores (from evaluation; legacy) */\n evaluatedCandidates: Annotation<EvaluatedCandidate[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Evaluated opportunities with actors (from entity-bundle evaluator) */\n evaluatedOpportunities: Annotation<EvaluatedOpportunity[]>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n // ─── Output Fields (Overwrite per turn) ───\n\n /** Final ranked and persisted opportunities */\n opportunities: Annotation<Opportunity[]>({\n reducer: (curr, next) => next,\n default: () => [],\n }),\n\n /** Discovery path: pairs skipped because an opportunity already exists between viewer and candidate (no duplicate created). */\n existingBetweenActors: Annotation<Array<{\n candidateUserId: Id<'users'>;\n networkId: Id<'networks'>;\n existingOpportunityId?: Id<'opportunities'>;\n existingStatus?: OpportunityStatus;\n reason?: 'same_trigger_recent_duplicate' | 'pair_active_negotiation' | 'final_atomic_conflict';\n existingTriggerIntentId?: string;\n }>>({\n reducer: (curr, next) => next ?? curr,\n default: () => [],\n }),\n\n /** Typed persist-node counts used by queue telemetry. */\n persistenceOutcome: Annotation<OpportunityPersistenceOutcome | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n /** Error message if any step fails */\n error: Annotation<string | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n /** Output for read mode: enriched list of opportunities. */\n readResult: Annotation<{\n count: number;\n message?: string;\n opportunities: Array<{\n id: string;\n indexName: string;\n connectedWith: string[];\n suggestedBy: string | null;\n reasoning: string;\n status: string;\n category: string;\n confidence: number | null;\n source: string | null;\n }>;\n } | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n /** Output for update/delete/send modes. */\n mutationResult: Annotation<{\n success: boolean;\n message?: string;\n opportunityId?: string;\n notified?: string[];\n conversationId?: string;\n error?: string;\n } | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n // ─── Trace Output ───\n\n /**\n * Accumulated trace entries from each graph node.\n * Used for observability: surfaces internal processing steps (search query, HyDE strategies,\n * candidates found, evaluation results) to the frontend.\n */\n trace: Annotation<Array<{ node: string; detail?: string; data?: Record<string, unknown> }>>({\n reducer: (curr, next) => [...curr, ...(next || [])],\n default: () => [],\n }),\n\n /** Timing records for each agent invocation within this graph run. */\n agentTimings: Annotation<DebugMetaAgent[]>({\n reducer: (acc, val) => [...acc, ...val],\n default: () => [],\n }),\n\n /**\n * Per-candidate negotiation records captured by `negotiateNode`. Populated\n * regardless of accept/reject so the question generator sees a complete\n * picture. Populated for ALL triggers (ambient + orchestrator) since the\n * negotiate node's `onCandidateResolved` hook is unconditional; only the\n * orchestrator streaming side-effects (opportunity_draft_ready emission)\n * are trigger-gated. Empty when the negotiate node was skipped (no\n * opportunities to negotiate).\n */\n discoveryNegotiations: Annotation<DiscoveryNegotiation[]>({\n reducer: (curr, next) => [...curr, ...(next || [])],\n default: () => [],\n }),\n\n /** Aggregate counters across `discoveryNegotiations`. Built in the negotiate node. */\n discoverySummary: Annotation<DiscoverySummary | null>({\n reducer: (_curr, next) => next ?? null,\n default: () => null,\n }),\n});\n"]}
|
|
@@ -483,6 +483,20 @@ export interface OpportunityNetworkEligibility {
|
|
|
483
483
|
/** When present, each actor network must remain assigned to this intent through commit. */
|
|
484
484
|
triggerIntentId?: string;
|
|
485
485
|
}
|
|
486
|
+
export type OpportunityDedupConflictReason = 'same_trigger_recent_duplicate' | 'pair_active_negotiation';
|
|
487
|
+
export interface OpportunityDedupConflict {
|
|
488
|
+
reason: OpportunityDedupConflictReason;
|
|
489
|
+
existingOpportunityId: string;
|
|
490
|
+
existingTriggerIntentId?: string;
|
|
491
|
+
existingStatus: OpportunityStatus;
|
|
492
|
+
existingCreatedAt: Date;
|
|
493
|
+
}
|
|
494
|
+
export type IntentScopedOpportunityPersistenceResult = {
|
|
495
|
+
created: Opportunity;
|
|
496
|
+
expired: Opportunity[];
|
|
497
|
+
} | {
|
|
498
|
+
conflict: OpportunityDedupConflict;
|
|
499
|
+
};
|
|
486
500
|
export interface CreateOpportunityData {
|
|
487
501
|
detection: OpportunityDetection;
|
|
488
502
|
actors: OpportunityActor[];
|
|
@@ -1126,6 +1140,15 @@ export interface Database {
|
|
|
1126
1140
|
* insert commit so concurrent removal cannot race opportunity creation.
|
|
1127
1141
|
*/
|
|
1128
1142
|
createOpportunityIfNetworkEligible?(data: CreateOpportunityData, eligibility: OpportunityNetworkEligibility): Promise<Opportunity | null>;
|
|
1143
|
+
/**
|
|
1144
|
+
* Intent-scoped discovery persistence boundary. Implementations serialize on
|
|
1145
|
+
* normalized participant pair + trigger intent, re-check same-trigger recent
|
|
1146
|
+
* duplicates and pair-global active negotiations, then create/expire while
|
|
1147
|
+
* the existing network eligibility locks remain held.
|
|
1148
|
+
*/
|
|
1149
|
+
persistIntentScopedOpportunityIfNetworkEligible?(data: CreateOpportunityData, expireIds: string[], eligibility: OpportunityNetworkEligibility & {
|
|
1150
|
+
triggerIntentId: string;
|
|
1151
|
+
}, dedupWindowMs: number): Promise<IntentScopedOpportunityPersistenceResult | null>;
|
|
1129
1152
|
/**
|
|
1130
1153
|
* Atomically update status only while the supplied participant anchors remain
|
|
1131
1154
|
* active and, when supplied, the opportunity still has `expectedStatus`.
|
|
@@ -1845,7 +1868,7 @@ export type PremiseGraphDatabase = Pick<Database, 'createPremise' | 'getPremise'
|
|
|
1845
1868
|
*
|
|
1846
1869
|
* Access layer: Both UserDatabase + SystemDatabase (orchestrates all operations)
|
|
1847
1870
|
*/
|
|
1848
|
-
export type ChatGraphCompositeDatabase = Pick<Database, 'getProfile' | 'getActiveIntents' | 'getActiveIntentsAcrossIndexes' | 'getIntentsInIndexForMember' | 'getUser' | 'updateUser' | 'getUserSocials' | 'setUserSocials' | 'saveProfile' | 'softDeleteGhost' | 'createIntent' | 'updateIntent' | 'archiveIntent' | 'createOpportunity' | 'createOpportunityIfNetworkEligible' | 'createOpportunityAndExpireIdsIfNetworkEligible' | 'updateOpportunityStatusIfNetworkEligible' | 'getOpportunity' | 'getOpportunitiesByIds' | 'opportunityExistsBetweenActors' | 'findOpportunitiesByActors' | 'getOpportunitiesForUser' | 'updateOpportunityStatus' | 'compensateTasklessNegotiatingOpportunity' | 'updateOpportunityActorApproval' | 'stampOpportunityActorAction' | 'getOrCreateDM' | 'getHydeDocument' | 'getHydeDocumentsForSource' | 'saveHydeDocument' | 'getIntent' | 'getPublicIndexesNotJoined' | 'getUserIndexIds' | 'getAssignmentNetworkMembershipsForUser' | 'getAssignmentNetworkIdsForUser' | 'getNetworkMemberships' | 'getNetworkMembership' | 'getActiveNetworkMembershipPairs' | 'getNetwork' | 'getNetworkWithPermissions' | 'getIntentForIndexing' | 'getNetworkMemberContext' | 'getNetworkAssignmentContext' | 'isIntentAssignedToIndex' | 'assignIntentToNetwork' | 'assignIntentToNetworkIfMember' | 'unassignIntentFromIndex' | 'getNetworkIdsForIntent' | 'getIntentIndexScores' | 'getPersonalIndexesForContact' | 'getOwnedIndexes' | 'isIndexOwner' | 'isNetworkMember' | 'getNetworkMembersForOwner' | 'getNetworkMembersForMember' | 'getMembersFromUserIndexes' | 'getNetworkIntentsForOwner' | 'getNetworkIntentsForMember' | 'updateIndexSettings' | 'softDeleteNetwork' | 'deleteProfile' | 'getProfileByUserId' | 'createNetwork' | 'getNetworkMemberCount' | 'addMemberToNetwork' | 'removeMemberFromIndex' | 'findDuplicateUser' | 'mergeGhostUser' | 'getPremisesForUser' | 'getPremisesForUserInNetworks' | 'createPremise' | 'getPremise' | 'updatePremise' | 'assignPremiseToNetwork' | 'getPremiseNetworks' | 'searchPremisesBySimilarity' | 'searchPremisesBySimilarityBatch' | 'getUserContext' | 'getUserContexts' | 'searchIntentsByContextEmbedding'> & Pick<NegotiationQueries, 'getNegotiationTaskForOpportunity'>;
|
|
1871
|
+
export type ChatGraphCompositeDatabase = Pick<Database, 'getProfile' | 'getActiveIntents' | 'getActiveIntentsAcrossIndexes' | 'getIntentsInIndexForMember' | 'getUser' | 'updateUser' | 'getUserSocials' | 'setUserSocials' | 'saveProfile' | 'softDeleteGhost' | 'createIntent' | 'updateIntent' | 'archiveIntent' | 'createOpportunity' | 'createOpportunityIfNetworkEligible' | 'createOpportunityAndExpireIdsIfNetworkEligible' | 'persistIntentScopedOpportunityIfNetworkEligible' | 'updateOpportunityStatusIfNetworkEligible' | 'getOpportunity' | 'getOpportunitiesByIds' | 'opportunityExistsBetweenActors' | 'findOpportunitiesByActors' | 'getOpportunitiesForUser' | 'updateOpportunityStatus' | 'compensateTasklessNegotiatingOpportunity' | 'updateOpportunityActorApproval' | 'stampOpportunityActorAction' | 'getOrCreateDM' | 'getHydeDocument' | 'getHydeDocumentsForSource' | 'saveHydeDocument' | 'getIntent' | 'getPublicIndexesNotJoined' | 'getUserIndexIds' | 'getAssignmentNetworkMembershipsForUser' | 'getAssignmentNetworkIdsForUser' | 'getNetworkMemberships' | 'getNetworkMembership' | 'getActiveNetworkMembershipPairs' | 'getNetwork' | 'getNetworkWithPermissions' | 'getIntentForIndexing' | 'getNetworkMemberContext' | 'getNetworkAssignmentContext' | 'isIntentAssignedToIndex' | 'assignIntentToNetwork' | 'assignIntentToNetworkIfMember' | 'unassignIntentFromIndex' | 'getNetworkIdsForIntent' | 'getIntentIndexScores' | 'getPersonalIndexesForContact' | 'getOwnedIndexes' | 'isIndexOwner' | 'isNetworkMember' | 'getNetworkMembersForOwner' | 'getNetworkMembersForMember' | 'getMembersFromUserIndexes' | 'getNetworkIntentsForOwner' | 'getNetworkIntentsForMember' | 'updateIndexSettings' | 'softDeleteNetwork' | 'deleteProfile' | 'getProfileByUserId' | 'createNetwork' | 'getNetworkMemberCount' | 'addMemberToNetwork' | 'removeMemberFromIndex' | 'findDuplicateUser' | 'mergeGhostUser' | 'getPremisesForUser' | 'getPremisesForUserInNetworks' | 'createPremise' | 'getPremise' | 'updatePremise' | 'assignPremiseToNetwork' | 'getPremiseNetworks' | 'searchPremisesBySimilarity' | 'searchPremisesBySimilarityBatch' | 'getUserContext' | 'getUserContexts' | 'searchIntentsByContextEmbedding'> & Pick<NegotiationQueries, 'getNegotiationTaskForOpportunity'>;
|
|
1849
1872
|
/**
|
|
1850
1873
|
* Database interface for Opportunity Graph operations.
|
|
1851
1874
|
* Includes prep/scope (network membership, intents, index details), persist (create, dedupe),
|
|
@@ -1853,7 +1876,7 @@ export type ChatGraphCompositeDatabase = Pick<Database, 'getProfile' | 'getActiv
|
|
|
1853
1876
|
*
|
|
1854
1877
|
* Access layer: SystemDatabase (cross-user opportunity operations)
|
|
1855
1878
|
*/
|
|
1856
|
-
export type OpportunityGraphDatabase = Pick<Database, 'getProfile' | 'createOpportunity' | 'createOpportunityIfNetworkEligible' | 'createOpportunityAndExpireIdsIfNetworkEligible' | 'updateOpportunityStatusIfNetworkEligible' | 'opportunityExistsBetweenActors' | 'findOpportunitiesByActors' | 'getUserIndexIds' | 'getNetworkMemberships' | 'getActiveNetworkMembershipPairs' | 'getActiveIntents' | 'getNetworkIdsForIntent' | 'getNetwork' | 'getNetworkMemberCount' | 'getIntentIndexScores' | 'getNetworkMemberContext' | 'getNetworkAssignmentContext' | 'getOpportunity' | 'getOpportunitiesForUser' | 'updateOpportunityStatus' | 'compensateTasklessNegotiatingOpportunity' | 'stampOpportunityActorAction' | 'updateOpportunityActorApproval' | 'isNetworkMember' | 'isIndexOwner' | 'getUser' | 'getOrCreateDM' | 'getIntent' | 'getPremisesForUser' | 'getPremisesForUserInNetworks' | 'searchPremisesBySimilarity' | 'searchPremisesBySimilarityBatch' | 'getUserContext' | 'getUserContexts' | 'searchIntentsByContextEmbedding' | 'getHydeDocumentsForSource'> & Pick<NegotiationQueries, 'getNegotiationTaskForOpportunity'>;
|
|
1879
|
+
export type OpportunityGraphDatabase = Pick<Database, 'getProfile' | 'createOpportunity' | 'createOpportunityIfNetworkEligible' | 'createOpportunityAndExpireIdsIfNetworkEligible' | 'persistIntentScopedOpportunityIfNetworkEligible' | 'updateOpportunityStatusIfNetworkEligible' | 'opportunityExistsBetweenActors' | 'findOpportunitiesByActors' | 'getUserIndexIds' | 'getNetworkMemberships' | 'getActiveNetworkMembershipPairs' | 'getActiveIntents' | 'getNetworkIdsForIntent' | 'getNetwork' | 'getNetworkMemberCount' | 'getIntentIndexScores' | 'getNetworkMemberContext' | 'getNetworkAssignmentContext' | 'getOpportunity' | 'getOpportunitiesForUser' | 'updateOpportunityStatus' | 'compensateTasklessNegotiatingOpportunity' | 'stampOpportunityActorAction' | 'updateOpportunityActorApproval' | 'isNetworkMember' | 'isIndexOwner' | 'getUser' | 'getOrCreateDM' | 'getIntent' | 'getPremisesForUser' | 'getPremisesForUserInNetworks' | 'searchPremisesBySimilarity' | 'searchPremisesBySimilarityBatch' | 'getUserContext' | 'getUserContexts' | 'searchIntentsByContextEmbedding' | 'getHydeDocumentsForSource'> & Pick<NegotiationQueries, 'getNegotiationTaskForOpportunity'>;
|
|
1857
1880
|
/**
|
|
1858
1881
|
* Negotiation-specific query operations not covered by generic
|
|
1859
1882
|
* conversation/task primitives.
|