@memberjunction/ai-vector-dupe 5.42.0 → 5.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,159 @@
1
+ /**
2
+ * @fileoverview Shared contract types for the duplicate-detection reasoning seam.
3
+ *
4
+ * These types are the pluggable boundary between the {@link DuplicateRecordDetector}
5
+ * pipeline and whichever {@link DuplicateReasoningProvider} (Prompt or Agent) actually
6
+ * reasons over a matched set. The input is a structural description of the entity plus
7
+ * the field-level deltas for one source record's candidate set; the output is a single
8
+ * structured verdict for that set. Both shipped providers emit the identical contract so
9
+ * promoting an entity from `Prompt` to `Agent` mode is a config change, not a rewrite.
10
+ *
11
+ * @module @memberjunction/ai-vector-dupe
12
+ */
13
+ import { UserInfo, IMetadataProvider } from '@memberjunction/core';
14
+ import { MJEntityDocumentEntity } from '@memberjunction/core-entities';
15
+ /** One record's value for a single differing field, addressed by record id. */
16
+ export interface ReasoningFieldValue {
17
+ /** The candidate/source record id (URL-segment composite key) this value belongs to. */
18
+ RecordID: string;
19
+ /** The field value held by that record (already stringified for the prompt; null when empty). */
20
+ Value: string | null;
21
+ }
22
+ /**
23
+ * The per-field delta passed to the reasoner. Only fields that differ across the set are
24
+ * included — identical fields are omitted so the reasoner focuses on what matters.
25
+ */
26
+ export interface ReasoningFieldDelta {
27
+ /** The field name. */
28
+ FieldName: string;
29
+ /** Per-record values for this field. */
30
+ Values: ReasoningFieldValue[];
31
+ }
32
+ /** Description of the source record (the current default survivor) being reasoned over. */
33
+ export interface ReasoningSourceRecord {
34
+ /** The source record id (URL-segment composite key). */
35
+ RecordID: string;
36
+ /** Human-readable label (name-field value, falling back to the key). */
37
+ Label: string;
38
+ /** Provenance hint (e.g. "Local"); free-form, surfaced in the instructions. */
39
+ Provenance: string;
40
+ /** Approximate count of dependent records, for the "cheapest to retain" heuristic. */
41
+ DependentCount: number;
42
+ }
43
+ /** Description of one vector-surfaced candidate match. */
44
+ export interface ReasoningCandidate {
45
+ /** The candidate record id (URL-segment composite key). */
46
+ RecordID: string;
47
+ /** Human-readable label. */
48
+ Label: string;
49
+ /** The raw vector similarity score (0–1) that surfaced this candidate. */
50
+ VectorScore: number;
51
+ /** Provenance hint. */
52
+ Provenance: string;
53
+ /** Approximate dependent-record count. */
54
+ DependentCount: number;
55
+ }
56
+ /**
57
+ * The complete input to a single reasoning call — one source record's matched set.
58
+ * This is assembled once per set by the detector (after all filtering) and is identical
59
+ * regardless of which provider runs.
60
+ */
61
+ export interface DuplicateReasoningInput {
62
+ /** Registered entity name (e.g. "Accounts"). */
63
+ EntityName: string;
64
+ /** Optional entity description for context. */
65
+ EntityDescription: string | null;
66
+ /** The entity document driving this run (carries the reasoning prompt/agent ids + mode). */
67
+ EntityDocument: MJEntityDocumentEntity;
68
+ /** The source record under review. */
69
+ SourceRecord: ReasoningSourceRecord;
70
+ /** The candidate matches for the source record. */
71
+ Candidates: ReasoningCandidate[];
72
+ /** The field-level deltas across the whole set (differing fields only). */
73
+ FieldDeltas: ReasoningFieldDelta[];
74
+ }
75
+ /** The recommendation verdict. */
76
+ export type DuplicateReasoningRecommendation = 'Merge' | 'NotDuplicate' | 'Uncertain';
77
+ /**
78
+ * The reasoner's verdict for ONE candidate, judged independently against the source. A matched
79
+ * set can mix true duplicates and false positives (vector search returns the top-K neighbors),
80
+ * so each candidate gets its own recommendation/confidence/reasoning — the detector stamps the
81
+ * per-candidate verdict onto that candidate's match row, never a blanket set-level verdict.
82
+ */
83
+ export interface DuplicateReasoningCandidateVerdict {
84
+ /** The candidate record id (must match one of the input candidates' RecordID). */
85
+ RecordID: string;
86
+ /** This candidate's verdict vs. the source record. */
87
+ Recommendation: DuplicateReasoningRecommendation;
88
+ /** This candidate's confidence (0–1), or null when the reasoner didn't return one. */
89
+ Confidence: number | null;
90
+ /** Short rationale specific to THIS candidate. */
91
+ Reasoning: string;
92
+ }
93
+ /**
94
+ * One per-field survivor choice from the reasoner: keep this field's value from the
95
+ * record identified by {@link SourceRecordID}. Resolved to a literal `{FieldName, Value}`
96
+ * for `Metadata.MergeRecords` at merge time.
97
+ */
98
+ export interface DuplicateReasoningFieldChoice {
99
+ /** The field whose surviving value is being chosen. */
100
+ FieldName: string;
101
+ /** The record id whose value should be kept for this field. */
102
+ SourceRecordID: string;
103
+ }
104
+ /**
105
+ * The structured verdict for a matched set. Persisted onto each match row's LLM* columns
106
+ * along with the run id of whichever provider ran.
107
+ */
108
+ export interface DuplicateReasoningOutput {
109
+ /** Whether the reasoning call itself succeeded (not whether it recommended a merge). */
110
+ Success: boolean;
111
+ /** Populated when {@link Success} is false. */
112
+ ErrorMessage?: string;
113
+ /**
114
+ * The overall verdict for the set, **derived** from the per-candidate verdicts (Merge if any
115
+ * candidate is a Merge, else Uncertain if any is Uncertain, else NotDuplicate). Used for the
116
+ * group's dominant display and the auto-merge gate — NOT stamped on individual candidate rows.
117
+ */
118
+ Recommendation: DuplicateReasoningRecommendation;
119
+ /**
120
+ * Overall confidence (0–1), derived from the per-candidate verdicts. `null` means no candidate
121
+ * returned a usable confidence — callers must distinguish this from a real `0` (which reads as
122
+ * "confidently NOT a duplicate") and render/store it as "unknown".
123
+ */
124
+ Confidence: number | null;
125
+ /** Overall human-readable summary of the set decision. */
126
+ Reasoning: string;
127
+ /**
128
+ * Per-candidate verdicts — the authoritative, row-level result. Each entry is judged
129
+ * independently against the source so a false-positive candidate reads NotDuplicate even when
130
+ * another candidate in the same set is a confident Merge.
131
+ */
132
+ CandidateVerdicts: DuplicateReasoningCandidateVerdict[];
133
+ /** The record id the reasoner proposes should survive (null when NotDuplicate). */
134
+ SurvivorRecordID: string | null;
135
+ /** Per-field survivor choices (only fields whose value comes from a non-survivor). */
136
+ FieldChoices: DuplicateReasoningFieldChoice[];
137
+ /**
138
+ * The AI Prompt Run id, when a {@link DuplicateReasoningProvider} ran via a single-shot
139
+ * prompt. Mutually exclusive with {@link AIAgentRunID}.
140
+ */
141
+ AIPromptRunID?: string | null;
142
+ /**
143
+ * The AI Agent Run id, when a {@link DuplicateReasoningProvider} ran via an agent.
144
+ * Mutually exclusive with {@link AIPromptRunID}.
145
+ */
146
+ AIAgentRunID?: string | null;
147
+ }
148
+ /**
149
+ * Per-call context threaded from the detector into the reasoning provider so the provider
150
+ * runs on the same request-scoped provider/user as the rest of the pipeline (multi-provider
151
+ * safety) rather than reaching for the global default.
152
+ */
153
+ export interface DuplicateReasoningContext {
154
+ /** The request-scoped metadata provider (server-side). */
155
+ Provider?: IMetadataProvider;
156
+ /** The context user for the run. */
157
+ ContextUser?: UserInfo;
158
+ }
159
+ //# sourceMappingURL=DuplicateReasoningTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DuplicateReasoningTypes.d.ts","sourceRoot":"","sources":["../../src/reasoning/DuplicateReasoningTypes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @fileoverview Shared contract types for the duplicate-detection reasoning seam.
3
+ *
4
+ * These types are the pluggable boundary between the {@link DuplicateRecordDetector}
5
+ * pipeline and whichever {@link DuplicateReasoningProvider} (Prompt or Agent) actually
6
+ * reasons over a matched set. The input is a structural description of the entity plus
7
+ * the field-level deltas for one source record's candidate set; the output is a single
8
+ * structured verdict for that set. Both shipped providers emit the identical contract so
9
+ * promoting an entity from `Prompt` to `Agent` mode is a config change, not a rewrite.
10
+ *
11
+ * @module @memberjunction/ai-vector-dupe
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=DuplicateReasoningTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DuplicateReasoningTypes.js","sourceRoot":"","sources":["../../src/reasoning/DuplicateReasoningTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @fileoverview Projects a matched set's field-level comparison into the lean shape the
3
+ * reasoning template expects ({@link ReasoningFieldDelta}).
4
+ *
5
+ * The record loading + field selection + delta computation lives **once** in
6
+ * `RecordComparisonEngine` (`@memberjunction/record-comparison`) — a low-level package
7
+ * both this dupe package and the server/UI comparison path can depend on without a build
8
+ * cycle. This adapter is the thin dupe-specific projection over that single engine:
9
+ *
10
+ * - it calls {@link RecordComparisonEngine.CompareRecordsForEntity} with the already-resolved
11
+ * `EntityInfo` and the detector's request-scoped `RunView` (so no redundant metadata
12
+ * lookup and no second RunView), then
13
+ * - keeps only the **differing** fields (the reasoner wants signal, not noise — the engine
14
+ * already drops fields that are empty across every record) and
15
+ * - flattens each cell to `{ RecordID: <key string>, Value: <stringified> }`.
16
+ *
17
+ * @module @memberjunction/ai-vector-dupe
18
+ */
19
+ import { RunView, CompositeKey, EntityInfo, UserInfo } from '@memberjunction/core';
20
+ import { RecordComparisonResult, RecordFieldValue } from '@memberjunction/record-comparison';
21
+ import { ReasoningFieldDelta } from './DuplicateReasoningTypes.js';
22
+ /**
23
+ * The result of building a matched set's deltas: the differing-field deltas the reasoner
24
+ * consumes, plus a record-id → human label map (derived from the same loaded records) so the
25
+ * caller can give the source AND candidates real names instead of raw GUIDs in the prompt.
26
+ */
27
+ export interface MatchedSetDelta {
28
+ /** Differing-field deltas (the reasoning payload). */
29
+ FieldDeltas: ReasoningFieldDelta[];
30
+ /** record-key string ({@link CompositeKey.Values}) → display label (name-field value, else key). */
31
+ Labels: Map<string, string>;
32
+ }
33
+ /**
34
+ * Builds the differing-field deltas for a matched set by delegating to the shared
35
+ * {@link RecordComparisonEngine} and projecting the result into {@link ReasoningFieldDelta}.
36
+ */
37
+ export declare class MatchedSetDeltaBuilder {
38
+ private readonly runView;
39
+ /**
40
+ * @param runView a RunView bound to the detector's request-scoped provider; threaded
41
+ * into the comparison engine so the load happens on the correct connection.
42
+ */
43
+ constructor(runView: RunView);
44
+ /**
45
+ * Build the field deltas for a matched set.
46
+ *
47
+ * @param entityInfo the entity being deduped (already resolved by the detector)
48
+ * @param keys the source key first, then each candidate key (order preserved)
49
+ * @param contextUser the run's context user
50
+ * @returns the differing-field deltas plus a record-id → label map; empty on load failure
51
+ */
52
+ Build(entityInfo: EntityInfo, keys: CompositeKey[], contextUser?: UserInfo): Promise<MatchedSetDelta>;
53
+ /**
54
+ * Map each loaded record's key string to its display label (the engine resolves the
55
+ * name-field value, falling back to the key). Lets the reasoner address records by name.
56
+ */
57
+ protected buildLabels(result: RecordComparisonResult): Map<string, string>;
58
+ /**
59
+ * Project the engine's rich delta matrix into the reasoning contract: differing fields
60
+ * only, each cell flattened to its record-key string + stringified value.
61
+ */
62
+ protected project(result: RecordComparisonResult): ReasoningFieldDelta[];
63
+ /** Stringify a loaded value for the prompt; null/undefined → null. */
64
+ protected toStringValue(value: RecordFieldValue): string | null;
65
+ }
66
+ //# sourceMappingURL=MatchedSetDeltaBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatchedSetDeltaBuilder.d.ts","sourceRoot":"","sources":["../../src/reasoning/MatchedSetDeltaBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAEH,sBAAsB,EACtB,gBAAgB,EACnB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC5B,sDAAsD;IACtD,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,oGAAoG;IACpG,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC;;;OAGG;gBACS,OAAO,EAAE,OAAO;IAI5B;;;;;;;OAOG;IACU,KAAK,CACd,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,YAAY,EAAE,EACpB,WAAW,CAAC,EAAE,QAAQ,GACvB,OAAO,CAAC,eAAe,CAAC;IAc3B;;;OAGG;IACH,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,sBAAsB,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAQ1E;;;OAGG;IACH,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,sBAAsB,GAAG,mBAAmB,EAAE;IAqBxE,sEAAsE;IACtE,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI;CAMlE"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @fileoverview Projects a matched set's field-level comparison into the lean shape the
3
+ * reasoning template expects ({@link ReasoningFieldDelta}).
4
+ *
5
+ * The record loading + field selection + delta computation lives **once** in
6
+ * `RecordComparisonEngine` (`@memberjunction/record-comparison`) — a low-level package
7
+ * both this dupe package and the server/UI comparison path can depend on without a build
8
+ * cycle. This adapter is the thin dupe-specific projection over that single engine:
9
+ *
10
+ * - it calls {@link RecordComparisonEngine.CompareRecordsForEntity} with the already-resolved
11
+ * `EntityInfo` and the detector's request-scoped `RunView` (so no redundant metadata
12
+ * lookup and no second RunView), then
13
+ * - keeps only the **differing** fields (the reasoner wants signal, not noise — the engine
14
+ * already drops fields that are empty across every record) and
15
+ * - flattens each cell to `{ RecordID: <key string>, Value: <stringified> }`.
16
+ *
17
+ * @module @memberjunction/ai-vector-dupe
18
+ */
19
+ import { RecordComparisonEngine, } from '@memberjunction/record-comparison';
20
+ /**
21
+ * Builds the differing-field deltas for a matched set by delegating to the shared
22
+ * {@link RecordComparisonEngine} and projecting the result into {@link ReasoningFieldDelta}.
23
+ */
24
+ export class MatchedSetDeltaBuilder {
25
+ /**
26
+ * @param runView a RunView bound to the detector's request-scoped provider; threaded
27
+ * into the comparison engine so the load happens on the correct connection.
28
+ */
29
+ constructor(runView) {
30
+ this.runView = runView;
31
+ }
32
+ /**
33
+ * Build the field deltas for a matched set.
34
+ *
35
+ * @param entityInfo the entity being deduped (already resolved by the detector)
36
+ * @param keys the source key first, then each candidate key (order preserved)
37
+ * @param contextUser the run's context user
38
+ * @returns the differing-field deltas plus a record-id → label map; empty on load failure
39
+ */
40
+ async Build(entityInfo, keys, contextUser) {
41
+ if (keys.length === 0) {
42
+ return { FieldDeltas: [], Labels: new Map() };
43
+ }
44
+ const engine = new RecordComparisonEngine();
45
+ const result = await engine.CompareRecordsForEntity(entityInfo, keys, contextUser, {
46
+ RunViewInstance: this.runView,
47
+ });
48
+ if (!result.Success) {
49
+ return { FieldDeltas: [], Labels: new Map() };
50
+ }
51
+ return { FieldDeltas: this.project(result), Labels: this.buildLabels(result) };
52
+ }
53
+ /**
54
+ * Map each loaded record's key string to its display label (the engine resolves the
55
+ * name-field value, falling back to the key). Lets the reasoner address records by name.
56
+ */
57
+ buildLabels(result) {
58
+ const labels = new Map();
59
+ for (const record of result.Records) {
60
+ labels.set(record.Key.Values(), record.Label);
61
+ }
62
+ return labels;
63
+ }
64
+ /**
65
+ * Project the engine's rich delta matrix into the reasoning contract: differing fields
66
+ * only, each cell flattened to its record-key string + stringified value.
67
+ */
68
+ project(result) {
69
+ // Column index → record-key string. This is the same addressing the reasoner uses to
70
+ // refer back to records (CompositeKey.Values()), so field choices resolve cleanly.
71
+ const recordIdByColumn = result.Records.map(r => r.Key.Values());
72
+ const deltas = [];
73
+ for (const field of result.Fields) {
74
+ if (!field.Differs) {
75
+ continue;
76
+ }
77
+ deltas.push({
78
+ FieldName: field.FieldName,
79
+ Values: field.Cells.map(cell => ({
80
+ RecordID: recordIdByColumn[cell.ColumnIndex],
81
+ Value: this.toStringValue(cell.Value),
82
+ })),
83
+ });
84
+ }
85
+ return deltas;
86
+ }
87
+ /** Stringify a loaded value for the prompt; null/undefined → null. */
88
+ toStringValue(value) {
89
+ if (value === null || value === undefined) {
90
+ return null;
91
+ }
92
+ return String(value);
93
+ }
94
+ }
95
+ //# sourceMappingURL=MatchedSetDeltaBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatchedSetDeltaBuilder.js","sourceRoot":"","sources":["../../src/reasoning/MatchedSetDeltaBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EACH,sBAAsB,GAGzB,MAAM,mCAAmC,CAAC;AAe3C;;;GAGG;AACH,MAAM,OAAO,sBAAsB;IAG/B;;;OAGG;IACH,YAAY,OAAgB;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,KAAK,CACd,UAAsB,EACtB,IAAoB,EACpB,WAAsB;QAEtB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;QAClD,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE;YAC/E,eAAe,EAAE,IAAI,CAAC,OAAO;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;QAClD,CAAC;QACD,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;IACnF,CAAC;IAED;;;OAGG;IACO,WAAW,CAAC,MAA8B;QAChD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;;OAGG;IACO,OAAO,CAAC,MAA8B;QAC5C,qFAAqF;QACrF,mFAAmF;QACnF,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAEjE,MAAM,MAAM,GAA0B,EAAE,CAAC;QACzC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBACjB,SAAS;YACb,CAAC;YACD,MAAM,CAAC,IAAI,CAAC;gBACR,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBAC7B,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC;oBAC5C,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;iBACxC,CAAC,CAAC;aACN,CAAC,CAAC;QACP,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,sEAAsE;IAC5D,aAAa,CAAC,KAAuB;QAC3C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;CACJ"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview Default ('Prompt' mode) reasoning provider.
3
+ *
4
+ * Runs the shared "Duplicate Resolution" instruction set as a single-shot
5
+ * `AIPromptRunner.ExecutePrompt` call — cheap, fast, no per-set agent run. Resolves the
6
+ * prompt from the Entity Document's `ReasoningPromptID` (falling back to the seeded
7
+ * "Duplicate Resolution" prompt by name), feeds it the shared template data, and persists
8
+ * the resulting `AIPromptRunID`.
9
+ *
10
+ * @module @memberjunction/ai-vector-dupe
11
+ */
12
+ import type { MJAIPromptEntityExtended } from '@memberjunction/ai-core-plus';
13
+ import { DuplicateReasoningProvider } from './DuplicateReasoningProvider.js';
14
+ import { DuplicateReasoningInput, DuplicateReasoningOutput, DuplicateReasoningContext } from './DuplicateReasoningTypes.js';
15
+ /**
16
+ * Single-shot prompt reasoning provider (the default). Registered under the 'Prompt'
17
+ * `ReasoningMode`.
18
+ */
19
+ export declare class PromptReasoningProvider extends DuplicateReasoningProvider {
20
+ /**
21
+ * Reason over a matched set via a single-shot prompt.
22
+ */
23
+ Reason(input: DuplicateReasoningInput, context: DuplicateReasoningContext): Promise<DuplicateReasoningOutput>;
24
+ /**
25
+ * Resolve the prompt from `ReasoningPromptID`, falling back to the seeded
26
+ * "Duplicate Resolution" prompt by name. Uses the AIEngine cache (no DB query).
27
+ */
28
+ protected resolvePrompt(input: DuplicateReasoningInput): MJAIPromptEntityExtended | null;
29
+ /** Build the params, execute, and translate the result into the reasoning contract. */
30
+ protected runPrompt(prompt: MJAIPromptEntityExtended, input: DuplicateReasoningInput, context: DuplicateReasoningContext): Promise<DuplicateReasoningOutput>;
31
+ }
32
+ //# sourceMappingURL=PromptReasoningProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptReasoningProvider.d.ts","sourceRoot":"","sources":["../../src/reasoning/PromptReasoningProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EACH,0BAA0B,EAE7B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACH,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EAC5B,MAAM,2BAA2B,CAAC;AAKnC;;;GAGG;AACH,qBACa,uBAAwB,SAAQ,0BAA0B;IACnE;;OAEG;IACU,MAAM,CACf,KAAK,EAAE,uBAAuB,EAC9B,OAAO,EAAE,yBAAyB,GACnC,OAAO,CAAC,wBAAwB,CAAC;IAqBpC;;;OAGG;IACH,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,GAAG,wBAAwB,GAAG,IAAI;IAYxF,uFAAuF;cACvE,SAAS,CACrB,MAAM,EAAE,wBAAwB,EAChC,KAAK,EAAE,uBAAuB,EAC9B,OAAO,EAAE,yBAAyB,GACnC,OAAO,CAAC,wBAAwB,CAAC;CAyBvC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @fileoverview Default ('Prompt' mode) reasoning provider.
3
+ *
4
+ * Runs the shared "Duplicate Resolution" instruction set as a single-shot
5
+ * `AIPromptRunner.ExecutePrompt` call — cheap, fast, no per-set agent run. Resolves the
6
+ * prompt from the Entity Document's `ReasoningPromptID` (falling back to the seeded
7
+ * "Duplicate Resolution" prompt by name), feeds it the shared template data, and persists
8
+ * the resulting `AIPromptRunID`.
9
+ *
10
+ * @module @memberjunction/ai-vector-dupe
11
+ */
12
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
13
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
14
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
15
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
16
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
17
+ };
18
+ import { LogError } from '@memberjunction/core';
19
+ import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
20
+ import { AIEngine } from '@memberjunction/aiengine';
21
+ import { AIPromptRunner } from '@memberjunction/ai-prompts';
22
+ import { AIPromptParams } from '@memberjunction/ai-core-plus';
23
+ import { DuplicateReasoningProvider, PROMPT_REASONING_PROVIDER_KEY } from './DuplicateReasoningProvider.js';
24
+ /** The name of the seeded prompt used when an Entity Document doesn't specify one. */
25
+ const DEFAULT_REASONING_PROMPT_NAME = 'Duplicate Resolution';
26
+ /**
27
+ * Single-shot prompt reasoning provider (the default). Registered under the 'Prompt'
28
+ * `ReasoningMode`.
29
+ */
30
+ let PromptReasoningProvider = class PromptReasoningProvider extends DuplicateReasoningProvider {
31
+ /**
32
+ * Reason over a matched set via a single-shot prompt.
33
+ */
34
+ async Reason(input, context) {
35
+ try {
36
+ await AIEngine.Instance.Config(false, context.ContextUser, context.Provider);
37
+ const prompt = this.resolvePrompt(input);
38
+ if (!prompt) {
39
+ return this.failedOutput(`No reasoning prompt resolved (ReasoningPromptID=${input.EntityDocument.ReasoningPromptID ?? 'null'}, fallback="${DEFAULT_REASONING_PROMPT_NAME}")`);
40
+ }
41
+ const result = await this.runPrompt(prompt, input, context);
42
+ if (!result.Success) {
43
+ return result;
44
+ }
45
+ return result;
46
+ }
47
+ catch (e) {
48
+ LogError(e);
49
+ return this.failedOutput(e instanceof Error ? e.message : String(e));
50
+ }
51
+ }
52
+ /**
53
+ * Resolve the prompt from `ReasoningPromptID`, falling back to the seeded
54
+ * "Duplicate Resolution" prompt by name. Uses the AIEngine cache (no DB query).
55
+ */
56
+ resolvePrompt(input) {
57
+ const prompts = AIEngine.Instance.Prompts;
58
+ const promptId = input.EntityDocument.ReasoningPromptID;
59
+ if (promptId) {
60
+ const byId = prompts.find(p => UUIDsEqual(p.ID, promptId));
61
+ if (byId) {
62
+ return byId;
63
+ }
64
+ }
65
+ return prompts.find(p => p.Name === DEFAULT_REASONING_PROMPT_NAME) ?? null;
66
+ }
67
+ /** Build the params, execute, and translate the result into the reasoning contract. */
68
+ async runPrompt(prompt, input, context) {
69
+ const params = new AIPromptParams();
70
+ params.prompt = prompt;
71
+ params.data = this.buildPromptData(input);
72
+ params.contextUser = context.ContextUser;
73
+ // Cheap LLM-based JSON-repair pass before AIPromptRunner falls back to a full
74
+ // re-run (the prompt's Strict ValidationBehavior + MaxRetries). Small reasoning
75
+ // models occasionally emit malformed JSON; this recovers most of those without
76
+ // re-spending a whole generation.
77
+ params.attemptJSONRepair = true;
78
+ const runner = new AIPromptRunner();
79
+ const runResult = await runner.ExecutePrompt(params);
80
+ const promptRunID = runResult.promptRun?.ID ?? null;
81
+ if (!runResult.success) {
82
+ const failed = this.failedOutput(runResult.errorMessage ?? 'Prompt execution failed');
83
+ failed.AIPromptRunID = promptRunID;
84
+ return failed;
85
+ }
86
+ const output = this.parseRawOutput(runResult.result ?? runResult.rawResult);
87
+ output.AIPromptRunID = promptRunID;
88
+ return output;
89
+ }
90
+ };
91
+ PromptReasoningProvider = __decorate([
92
+ RegisterClass(DuplicateReasoningProvider, PROMPT_REASONING_PROVIDER_KEY)
93
+ ], PromptReasoningProvider);
94
+ export { PromptReasoningProvider };
95
+ //# sourceMappingURL=PromptReasoningProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptReasoningProvider.js","sourceRoot":"","sources":["../../src/reasoning/PromptReasoningProvider.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/ai-vector-dupe",
3
3
  "type": "module",
4
- "version": "5.42.0",
4
+ "version": "5.44.0",
5
5
  "description": "MemberJunction: AI Vector/Entity Sync Package - Handles synchronization between Vector DB and MJ CDP Data",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -17,15 +17,18 @@
17
17
  "author": "MemberJunction.com",
18
18
  "license": "ISC",
19
19
  "dependencies": {
20
- "@memberjunction/ai": "5.42.0",
21
- "@memberjunction/ai-vectordb": "5.42.0",
22
- "@memberjunction/ai-vectors": "5.42.0",
23
- "@memberjunction/templates": "5.42.0",
24
- "@memberjunction/ai-vector-sync": "5.42.0",
25
- "@memberjunction/aiengine": "5.42.0",
26
- "@memberjunction/core": "5.42.0",
27
- "@memberjunction/global": "5.42.0",
28
- "@memberjunction/core-entities": "5.42.0",
20
+ "@memberjunction/ai": "5.44.0",
21
+ "@memberjunction/ai-vectordb": "5.44.0",
22
+ "@memberjunction/ai-core-plus": "5.44.0",
23
+ "@memberjunction/ai-prompts": "5.44.0",
24
+ "@memberjunction/ai-vectors": "5.44.0",
25
+ "@memberjunction/templates": "5.44.0",
26
+ "@memberjunction/ai-vector-sync": "5.44.0",
27
+ "@memberjunction/aiengine": "5.44.0",
28
+ "@memberjunction/core": "5.44.0",
29
+ "@memberjunction/global": "5.44.0",
30
+ "@memberjunction/core-entities": "5.44.0",
31
+ "@memberjunction/record-comparison": "5.44.0",
29
32
  "dotenv": "^17.2.4"
30
33
  },
31
34
  "devDependencies": {