@memberjunction/core-entities 6.1.3 → 6.1.4
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.
|
@@ -834,12 +834,27 @@ export declare class ConversationEngine extends BaseEngine<ConversationEngine> {
|
|
|
834
834
|
*/
|
|
835
835
|
protected HandleIndividualBaseEntityEvent(event: BaseEntityEvent): Promise<boolean>;
|
|
836
836
|
/**
|
|
837
|
-
*
|
|
838
|
-
*
|
|
839
|
-
*
|
|
840
|
-
*
|
|
837
|
+
* Will anything below actually use the row, or does the primary key suffice?
|
|
838
|
+
*
|
|
839
|
+
* Asked BEFORE hydrating, because for a remote event whose entity is not on the server's
|
|
840
|
+
* broadcast allowlist, hydrating costs a read through the provider. This dispatcher runs in
|
|
841
|
+
* every connected browser, for every save of these entities anywhere in the system — and
|
|
842
|
+
* conversation details are the hottest write path in the product, so an unconditional read
|
|
843
|
+
* here is one round trip per connected client per message, nearly all of them refused for a
|
|
844
|
+
* session with no claim to the record.
|
|
845
|
+
*
|
|
846
|
+
* Every `false` below is a case where the handler already returns early without touching the
|
|
847
|
+
* row, so skipping the read changes nothing a caller can observe.
|
|
848
|
+
*/
|
|
849
|
+
private eventNeedsRow;
|
|
850
|
+
/**
|
|
851
|
+
* This record's id, from the primary key the event always carries.
|
|
852
|
+
*
|
|
853
|
+
* Prefers the key over the row: the key is broadcast unconditionally, whereas the row is only
|
|
854
|
+
* present for allowlisted entities or after a re-read. Falls back to the row's `ID` so a
|
|
855
|
+
* single-column entity still resolves if the key is ever absent.
|
|
841
856
|
*/
|
|
842
|
-
private
|
|
857
|
+
private eventRecordID;
|
|
843
858
|
/**
|
|
844
859
|
* Safely merges data onto a target object that may or may not be a BaseEntity.
|
|
845
860
|
* If the target has SetMany (i.e., it's a BaseEntity), uses that to properly handle
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../src/engines/conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,eAAe,
|
|
1
|
+
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../src/engines/conversations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseEngine, RunQuery, RunView, TransformSimpleObjectToEntityObject } from "@memberjunction/core";
|
|
1
|
+
import { BaseEngine, EntityEventRowIsFree, ResolveEntityEventKey, ResolveEntityEventRow, RunQuery, RunView, TransformSimpleObjectToEntityObject } from "@memberjunction/core";
|
|
2
2
|
import { NormalizeUUID, ToEpochMs, UUIDsEqual } from "@memberjunction/global";
|
|
3
3
|
import { BehaviorSubject } from "rxjs";
|
|
4
4
|
import { ArtifactMetadataEngine } from "./artifacts.js";
|
|
@@ -1782,46 +1782,130 @@ export class ConversationEngine extends BaseEngine {
|
|
|
1782
1782
|
const effectiveType = event.type === 'remote-invalidate'
|
|
1783
1783
|
? event.payload?.action || 'save'
|
|
1784
1784
|
: event.type;
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
if (
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1785
|
+
const handled = normalizedName === 'mj: conversations' ||
|
|
1786
|
+
normalizedName === 'mj: conversation details' ||
|
|
1787
|
+
normalizedName === 'mj: projects' ||
|
|
1788
|
+
normalizedName === 'mj: ai agent runs' ||
|
|
1789
|
+
normalizedName === 'mj: conversation detail artifacts' ||
|
|
1790
|
+
normalizedName === 'mj: conversation detail ratings';
|
|
1791
|
+
if (handled) {
|
|
1792
|
+
// Hydrate ONCE, here, because this is the only async frame on the path. A remote event
|
|
1793
|
+
// carries the row only for entities on the server's broadcast allowlist (see
|
|
1794
|
+
// `cacheSettings.recordDataBroadcastEntities`); otherwise this re-reads the single
|
|
1795
|
+
// record through the provider, as this user, so access control decides what comes
|
|
1796
|
+
// back. Handlers below stay synchronous and simply receive the row — passing it down
|
|
1797
|
+
// rather than letting each fetch its own keeps this to one read per event and avoids
|
|
1798
|
+
// turning five handlers async for a value the dispatcher can obtain once.
|
|
1799
|
+
// ...and only when something below will actually use it — see eventNeedsRow. On a
|
|
1800
|
+
// remote event without `recordData`, hydrating means a read through the provider, and
|
|
1801
|
+
// this dispatcher runs in EVERY connected browser for every save of these entities
|
|
1802
|
+
// anywhere in the system, whether or not this session has any claim to the record.
|
|
1803
|
+
const row = this.eventNeedsRow(event, normalizedName, effectiveType)
|
|
1804
|
+
? await ResolveEntityEventRow(event, this.ProviderToUse, this.ContextUser)
|
|
1805
|
+
: null;
|
|
1806
|
+
if (normalizedName === 'mj: conversations') {
|
|
1807
|
+
return this.handleConversationEntityEvent(event, effectiveType, row);
|
|
1808
|
+
}
|
|
1809
|
+
if (normalizedName === 'mj: conversation details') {
|
|
1810
|
+
return this.handleConversationDetailEntityEvent(event, effectiveType, row);
|
|
1811
|
+
}
|
|
1812
|
+
if (normalizedName === 'mj: projects') {
|
|
1813
|
+
return this.handleProjectEntityEvent(event, effectiveType, row);
|
|
1814
|
+
}
|
|
1815
|
+
if (normalizedName === 'mj: ai agent runs') {
|
|
1816
|
+
return this.handleAgentRunEntityEvent(event, effectiveType, row);
|
|
1817
|
+
}
|
|
1818
|
+
return this.handlePeripheralJunctionEntityEvent(event, row);
|
|
1799
1819
|
}
|
|
1800
1820
|
// Not a conversation entity — let BaseEngine handle it
|
|
1801
1821
|
return await super.HandleIndividualBaseEntityEvent(event);
|
|
1802
1822
|
}
|
|
1803
1823
|
/**
|
|
1804
|
-
*
|
|
1805
|
-
*
|
|
1806
|
-
*
|
|
1807
|
-
*
|
|
1824
|
+
* Will anything below actually use the row, or does the primary key suffice?
|
|
1825
|
+
*
|
|
1826
|
+
* Asked BEFORE hydrating, because for a remote event whose entity is not on the server's
|
|
1827
|
+
* broadcast allowlist, hydrating costs a read through the provider. This dispatcher runs in
|
|
1828
|
+
* every connected browser, for every save of these entities anywhere in the system — and
|
|
1829
|
+
* conversation details are the hottest write path in the product, so an unconditional read
|
|
1830
|
+
* here is one round trip per connected client per message, nearly all of them refused for a
|
|
1831
|
+
* session with no claim to the record.
|
|
1832
|
+
*
|
|
1833
|
+
* Every `false` below is a case where the handler already returns early without touching the
|
|
1834
|
+
* row, so skipping the read changes nothing a caller can observe.
|
|
1808
1835
|
*/
|
|
1809
|
-
|
|
1810
|
-
//
|
|
1811
|
-
|
|
1812
|
-
|
|
1836
|
+
eventNeedsRow(event, normalizedName, effectiveType) {
|
|
1837
|
+
// A row that costs nothing is never worth skipping. Free for a local event (the row IS the
|
|
1838
|
+
// live entity) and for a remote event whose payload already carries `recordData`, because
|
|
1839
|
+
// the entity is on the server's broadcast allowlist.
|
|
1840
|
+
//
|
|
1841
|
+
// This has to come first, and the per-entity reasoning below has to be read as being about
|
|
1842
|
+
// THE READ. Applying it to a free row is what dropped a remote project save: the save
|
|
1843
|
+
// branch uses EnvironmentID and IsArchived off the row, and with the row nulled it read
|
|
1844
|
+
// them as undefined/false, concluded the project was outside the loaded environment, and
|
|
1845
|
+
// filtered it out of the list — for exactly the sessions displaying it.
|
|
1846
|
+
if (EntityEventRowIsFree(event)) {
|
|
1847
|
+
return true;
|
|
1813
1848
|
}
|
|
1814
|
-
//
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1849
|
+
// Projects: a DELETE needs only the id. A SAVE genuinely uses the row — `EnvironmentID` and
|
|
1850
|
+
// `IsArchived` are what decide whether the project stays in the list — so it has to be
|
|
1851
|
+
// hydrated whenever we hold the project.
|
|
1852
|
+
//
|
|
1853
|
+
// The earlier reasoning here ("a save that got this far has nothing to merge regardless")
|
|
1854
|
+
// was true of the MERGE and false of the branch beside it: without the row, `EnvironmentID`
|
|
1855
|
+
// reads as absent, `inLoadedEnvironment` comes out false for any session that has loaded an
|
|
1856
|
+
// environment, and the save REMOVES the project instead. That is precisely the cross-client
|
|
1857
|
+
// case this change exists to serve, so it is gated like conversations are: when we do not
|
|
1858
|
+
// hold the project the remote path does nothing anyway (the append branch below requires
|
|
1859
|
+
// `event.baseEntity`), and the row would be fetched only to be discarded.
|
|
1860
|
+
if (normalizedName === 'mj: projects') {
|
|
1861
|
+
if (effectiveType !== 'save') {
|
|
1862
|
+
return false;
|
|
1819
1863
|
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1864
|
+
const id = this.eventRecordID(event, null);
|
|
1865
|
+
return !!id && this._projects$.value.some(p => UUIDsEqual(p.ID, id));
|
|
1866
|
+
}
|
|
1867
|
+
if (normalizedName === 'mj: conversations') {
|
|
1868
|
+
// A delete needs only the id. A save merges fields onto a conversation we already
|
|
1869
|
+
// hold — and when we do not hold it, the remote branch of the handler does nothing,
|
|
1870
|
+
// so the row would be fetched only to be discarded.
|
|
1871
|
+
if (effectiveType !== 'save') {
|
|
1872
|
+
return false;
|
|
1822
1873
|
}
|
|
1874
|
+
const id = this.eventRecordID(event, null);
|
|
1875
|
+
return !!id && !!this.GetConversation(id);
|
|
1876
|
+
}
|
|
1877
|
+
// Details, agent runs and the junction entities all resolve through the detail cache and
|
|
1878
|
+
// return early when the conversation they name is not in it.
|
|
1879
|
+
//
|
|
1880
|
+
// A remote DELETE can never be served: the record is gone, so the re-read comes back null
|
|
1881
|
+
// and every one of those handlers early-returns on the missing foreign key. The round trip
|
|
1882
|
+
// could not change an outcome, so it is not made. (That these handlers cannot act on a
|
|
1883
|
+
// remote delete at all is a pre-existing gap — deletes never carried `recordData` at either
|
|
1884
|
+
// publish site — and is not what this method is for.) Local deletes are unaffected: the
|
|
1885
|
+
// free-row check above already returned true for them.
|
|
1886
|
+
if (effectiveType === 'delete') {
|
|
1887
|
+
return false;
|
|
1888
|
+
}
|
|
1889
|
+
// With the cache empty — any session that has not opened a conversation — none of them can
|
|
1890
|
+
// do anything, whatever the row says. (A non-empty cache still needs the read:
|
|
1891
|
+
// ConversationID is a foreign key, so the primary key cannot tell us whether this detail
|
|
1892
|
+
// belongs to a conversation we hold.)
|
|
1893
|
+
return this._detailCache.size > 0;
|
|
1894
|
+
}
|
|
1895
|
+
/**
|
|
1896
|
+
* This record's id, from the primary key the event always carries.
|
|
1897
|
+
*
|
|
1898
|
+
* Prefers the key over the row: the key is broadcast unconditionally, whereas the row is only
|
|
1899
|
+
* present for allowlisted entities or after a re-read. Falls back to the row's `ID` so a
|
|
1900
|
+
* single-column entity still resolves if the key is ever absent.
|
|
1901
|
+
*/
|
|
1902
|
+
eventRecordID(event, data) {
|
|
1903
|
+
const key = ResolveEntityEventKey(event);
|
|
1904
|
+
const fromKey = key?.KeyValuePairs?.find(kv => kv.FieldName?.toLowerCase() === 'id')?.Value;
|
|
1905
|
+
if (fromKey != null && String(fromKey).length > 0) {
|
|
1906
|
+
return String(fromKey);
|
|
1823
1907
|
}
|
|
1824
|
-
return
|
|
1908
|
+
return data?.['ID'];
|
|
1825
1909
|
}
|
|
1826
1910
|
/**
|
|
1827
1911
|
* Safely merges data onto a target object that may or may not be a BaseEntity.
|
|
@@ -1840,12 +1924,21 @@ export class ConversationEngine extends BaseEngine {
|
|
|
1840
1924
|
/**
|
|
1841
1925
|
* Handles save/delete events on Conversation entities from local or remote code.
|
|
1842
1926
|
*/
|
|
1843
|
-
handleConversationEntityEvent(event, action) {
|
|
1844
|
-
|
|
1845
|
-
|
|
1927
|
+
handleConversationEntityEvent(event, action, data) {
|
|
1928
|
+
// Identity comes from the primary key, which is broadcast unconditionally — a delete needs
|
|
1929
|
+
// nothing else, so it no longer depends on the row being available.
|
|
1930
|
+
const id = this.eventRecordID(event, data);
|
|
1846
1931
|
if (!id)
|
|
1847
1932
|
return true;
|
|
1848
1933
|
if (action === 'save') {
|
|
1934
|
+
// Same reasoning as handleProjectEntityEvent: the row can be null even when
|
|
1935
|
+
// `eventNeedsRow` said yes, because the re-read can be refused, find the record gone,
|
|
1936
|
+
// or simply fail — all of which `ResolveEntityEventRow` reports as null rather than
|
|
1937
|
+
// throwing. `mergeDataOntoRecord` would hand that null to `BaseEntity.SetMany`, which
|
|
1938
|
+
// throws, and nothing above this frame catches it. A conversation we cannot re-read
|
|
1939
|
+
// stays as it was; the next `LoadConversations` corrects it.
|
|
1940
|
+
if (!data)
|
|
1941
|
+
return true;
|
|
1849
1942
|
const existing = this.GetConversation(id);
|
|
1850
1943
|
if (existing) {
|
|
1851
1944
|
this.mergeDataOntoRecord(existing, data);
|
|
@@ -1879,10 +1972,11 @@ export class ConversationEngine extends BaseEngine {
|
|
|
1879
1972
|
/**
|
|
1880
1973
|
* Handles save/delete events on ConversationDetail entities from local or remote code.
|
|
1881
1974
|
*/
|
|
1882
|
-
handleConversationDetailEntityEvent(event, action) {
|
|
1975
|
+
handleConversationDetailEntityEvent(event, action, data) {
|
|
1883
1976
|
const entity = event.baseEntity;
|
|
1884
|
-
const
|
|
1885
|
-
|
|
1977
|
+
const id = this.eventRecordID(event, data);
|
|
1978
|
+
// ConversationID is a foreign key, so the primary key cannot supply it — this is the field
|
|
1979
|
+
// the dispatcher's re-read exists to obtain.
|
|
1886
1980
|
const conversationId = data?.['ConversationID'];
|
|
1887
1981
|
if (!id || !conversationId)
|
|
1888
1982
|
return true;
|
|
@@ -1924,9 +2018,8 @@ export class ConversationEngine extends BaseEngine {
|
|
|
1924
2018
|
* deleted via the project form modal. Only tracks projects in the currently-loaded
|
|
1925
2019
|
* environment; archived projects are dropped from the active list.
|
|
1926
2020
|
*/
|
|
1927
|
-
handleProjectEntityEvent(event, action) {
|
|
1928
|
-
const
|
|
1929
|
-
const id = data?.['ID'];
|
|
2021
|
+
handleProjectEntityEvent(event, action, data) {
|
|
2022
|
+
const id = this.eventRecordID(event, data);
|
|
1930
2023
|
if (!id)
|
|
1931
2024
|
return true;
|
|
1932
2025
|
const current = this._projects$.value;
|
|
@@ -1937,9 +2030,32 @@ export class ConversationEngine extends BaseEngine {
|
|
|
1937
2030
|
}
|
|
1938
2031
|
return true;
|
|
1939
2032
|
}
|
|
1940
|
-
//
|
|
1941
|
-
|
|
1942
|
-
|
|
2033
|
+
// WITHOUT THE ROW WE KNOW NOTHING, and must not guess. Every field below would read as
|
|
2034
|
+
// absent: `IsArchived` becomes false, which is harmless, but `EnvironmentID` becomes
|
|
2035
|
+
// undefined — and "no environment" is indistinguishable from "moved to another one", so the
|
|
2036
|
+
// branch that DROPS the project is the one that runs. Leaving it untouched is the only
|
|
2037
|
+
// honest response to a row we do not have.
|
|
2038
|
+
//
|
|
2039
|
+
// `eventNeedsRow` is supposed to guarantee this never happens for a project we hold, but
|
|
2040
|
+
// that contract is enforced by a comment and `strictNullChecks` is off in this package, so
|
|
2041
|
+
// the guarantee is restated here where the damage would be done. Hydration can also simply
|
|
2042
|
+
// fail: `ResolveEntityEventRow` returns null rather than throwing.
|
|
2043
|
+
//
|
|
2044
|
+
// KEEPING IT IS DELIBERATE EVEN WHEN THE ROW WAS WITHHELD ON PURPOSE. A null can mean the
|
|
2045
|
+
// re-read was refused — the viewer may no longer read this project — or that it failed.
|
|
2046
|
+
// The two are indistinguishable here, and they want opposite responses, so this takes the
|
|
2047
|
+
// one whose wrong case is recoverable: a stale row in a sidebar is corrected by the next
|
|
2048
|
+
// `LoadProjects`, whereas a project deleted from the UI on a transient read failure is
|
|
2049
|
+
// gone until the user reloads and cannot be told why.
|
|
2050
|
+
if (!data) {
|
|
2051
|
+
return true;
|
|
2052
|
+
}
|
|
2053
|
+
// save — only track projects in the loaded environment; drop archived ones.
|
|
2054
|
+
// No `?.` past the guard above: `data` is non-null here, and optional chaining would say
|
|
2055
|
+
// otherwise. It is also what let `mergeDataOntoRecord(…, data)` accept a nullable argument
|
|
2056
|
+
// without complaint, since `strictNullChecks` is off in this package.
|
|
2057
|
+
const environmentId = data['EnvironmentID'];
|
|
2058
|
+
const isArchived = data['IsArchived'] === true;
|
|
1943
2059
|
const inLoadedEnvironment = !this._lastProjectsEnvironmentId ||
|
|
1944
2060
|
(environmentId != null && UUIDsEqual(environmentId, this._lastProjectsEnvironmentId));
|
|
1945
2061
|
if (existingIdx >= 0) {
|
|
@@ -1961,9 +2077,9 @@ export class ConversationEngine extends BaseEngine {
|
|
|
1961
2077
|
* Handles save/delete events on AI Agent Run entities from local or remote code.
|
|
1962
2078
|
* Updates the AgentRunsByDetailId map so timers and status reflect reality.
|
|
1963
2079
|
*/
|
|
1964
|
-
handleAgentRunEntityEvent(event, action) {
|
|
1965
|
-
const
|
|
1966
|
-
|
|
2080
|
+
handleAgentRunEntityEvent(event, action, data) {
|
|
2081
|
+
const id = this.eventRecordID(event, data);
|
|
2082
|
+
// Foreign key, not part of this row's primary key — supplied by the dispatcher's re-read.
|
|
1967
2083
|
const detailId = data?.['ConversationDetailID'];
|
|
1968
2084
|
if (!id || !detailId)
|
|
1969
2085
|
return true;
|
|
@@ -2000,8 +2116,9 @@ export class ConversationEngine extends BaseEngine {
|
|
|
2000
2116
|
* reconstructed from the entity event alone, so we flag the cache as stale.
|
|
2001
2117
|
* The UI component checks PeripheralDataStale and force-refreshes when needed.
|
|
2002
2118
|
*/
|
|
2003
|
-
handlePeripheralJunctionEntityEvent(event) {
|
|
2004
|
-
|
|
2119
|
+
handlePeripheralJunctionEntityEvent(event, data) {
|
|
2120
|
+
// The junction's own primary key is not useful here; what matters is which detail it hangs
|
|
2121
|
+
// off, which is a foreign key and therefore only available from the row.
|
|
2005
2122
|
const detailId = data?.['ConversationDetailID'];
|
|
2006
2123
|
if (!detailId)
|
|
2007
2124
|
return true;
|