@memberjunction/core-entities-server 5.37.0 → 5.39.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.
Files changed (38) hide show
  1. package/dist/custom/IntegrationLLMPKCallback.d.ts +30 -0
  2. package/dist/custom/IntegrationLLMPKCallback.d.ts.map +1 -0
  3. package/dist/custom/IntegrationLLMPKCallback.js +123 -0
  4. package/dist/custom/IntegrationLLMPKCallback.js.map +1 -0
  5. package/dist/custom/MJAIPromptRunEntityServer.server.d.ts.map +1 -1
  6. package/dist/custom/MJAIPromptRunEntityServer.server.js +14 -4
  7. package/dist/custom/MJAIPromptRunEntityServer.server.js.map +1 -1
  8. package/dist/custom/MJCompanyIntegrationEntityServer.server.d.ts +94 -0
  9. package/dist/custom/MJCompanyIntegrationEntityServer.server.d.ts.map +1 -0
  10. package/dist/custom/MJCompanyIntegrationEntityServer.server.js +207 -0
  11. package/dist/custom/MJCompanyIntegrationEntityServer.server.js.map +1 -0
  12. package/dist/custom/MJEntityDocumentEntityServer.server.d.ts +69 -0
  13. package/dist/custom/MJEntityDocumentEntityServer.server.d.ts.map +1 -0
  14. package/dist/custom/MJEntityDocumentEntityServer.server.js +245 -0
  15. package/dist/custom/MJEntityDocumentEntityServer.server.js.map +1 -0
  16. package/dist/custom/MJQueryEntityServer.server.d.ts +8 -24
  17. package/dist/custom/MJQueryEntityServer.server.d.ts.map +1 -1
  18. package/dist/custom/MJQueryEntityServer.server.js +22 -109
  19. package/dist/custom/MJQueryEntityServer.server.js.map +1 -1
  20. package/dist/custom/query-extraction/parse.js +1 -1
  21. package/dist/custom/query-extraction/parse.js.map +1 -1
  22. package/dist/custom/query-extraction/pipeline.d.ts.map +1 -1
  23. package/dist/custom/query-extraction/pipeline.js +2 -1
  24. package/dist/custom/query-extraction/pipeline.js.map +1 -1
  25. package/dist/custom/query-extraction/resolve.d.ts +7 -6
  26. package/dist/custom/query-extraction/resolve.d.ts.map +1 -1
  27. package/dist/custom/query-extraction/resolve.js +18 -16
  28. package/dist/custom/query-extraction/resolve.js.map +1 -1
  29. package/dist/custom/query-extraction/sync.d.ts.map +1 -1
  30. package/dist/custom/query-extraction/sync.js +24 -14
  31. package/dist/custom/query-extraction/sync.js.map +1 -1
  32. package/dist/custom/query-extraction/types.d.ts +3 -2
  33. package/dist/custom/query-extraction/types.d.ts.map +1 -1
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -0
  37. package/dist/index.js.map +1 -1
  38. package/package.json +24 -22
@@ -0,0 +1,30 @@
1
+ /**
2
+ * LLM PK inference callback used by SoftPKClassifier's LLM tier.
3
+ *
4
+ * The classifier cascade is:
5
+ * universal-convention → naming-heuristic → statistical → LLM → none
6
+ *
7
+ * When the deterministic tiers all yield no confident nominee, this callback
8
+ * gets called with the object name + field list (plus sample rows when
9
+ * available) and returns the LLM's best guess of a primary-key field. If
10
+ * the LLM also can't identify one, the verdict comes back `none` and the
11
+ * pipeline drops the IO (only for `MetadataSource='Discovered'`).
12
+ *
13
+ * Model selection: highest-priority active LanguageModel from AIEngine.
14
+ * API key: resolved via the central AIAPIKeys registry (no AI vendor key
15
+ * reading happens in this file — `GetAIAPIKeyGlobal` is the central
16
+ * server-side gate).
17
+ *
18
+ * If AIEngine has no active language model, or the model's driver can't be
19
+ * resolved, the callback returns a `nominee: null, confidence: 0`
20
+ * (skip-the-LLM-tier) result — never a fabricated PK.
21
+ */
22
+ import { type UserInfo } from '@memberjunction/core';
23
+ import type { LLMOneShotCallback } from '@memberjunction/integration-pk-classifier';
24
+ /**
25
+ * Builds an `LLMOneShotCallback` that calls a server-side LLM to infer a PK.
26
+ * Returns `null` if AIEngine isn't loadable or no language model is active —
27
+ * pipeline silently skips the LLM tier in that case (verdict cascades to `none`).
28
+ */
29
+ export declare function buildIntegrationLLMPKCallback(contextUser: UserInfo): Promise<LLMOneShotCallback | null>;
30
+ //# sourceMappingURL=IntegrationLLMPKCallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrationLLMPKCallback.d.ts","sourceRoot":"","sources":["../../src/custom/IntegrationLLMPKCallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAK1E,OAAO,KAAK,EACR,kBAAkB,EAGrB,MAAM,2CAA2C,CAAC;AAEnD;;;;GAIG;AACH,wBAAsB,6BAA6B,CAC/C,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA0GpC"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * LLM PK inference callback used by SoftPKClassifier's LLM tier.
3
+ *
4
+ * The classifier cascade is:
5
+ * universal-convention → naming-heuristic → statistical → LLM → none
6
+ *
7
+ * When the deterministic tiers all yield no confident nominee, this callback
8
+ * gets called with the object name + field list (plus sample rows when
9
+ * available) and returns the LLM's best guess of a primary-key field. If
10
+ * the LLM also can't identify one, the verdict comes back `none` and the
11
+ * pipeline drops the IO (only for `MetadataSource='Discovered'`).
12
+ *
13
+ * Model selection: highest-priority active LanguageModel from AIEngine.
14
+ * API key: resolved via the central AIAPIKeys registry (no AI vendor key
15
+ * reading happens in this file — `GetAIAPIKeyGlobal` is the central
16
+ * server-side gate).
17
+ *
18
+ * If AIEngine has no active language model, or the model's driver can't be
19
+ * resolved, the callback returns a `nominee: null, confidence: 0`
20
+ * (skip-the-LLM-tier) result — never a fabricated PK.
21
+ */
22
+ import { LogError, LogStatus } from '@memberjunction/core';
23
+ import { MJGlobal } from '@memberjunction/global';
24
+ import { BaseLLM } from '@memberjunction/ai';
25
+ import { GetAIAPIKeyGlobal } from '@memberjunction/ai';
26
+ import { AIEngine } from '@memberjunction/aiengine';
27
+ /**
28
+ * Builds an `LLMOneShotCallback` that calls a server-side LLM to infer a PK.
29
+ * Returns `null` if AIEngine isn't loadable or no language model is active —
30
+ * pipeline silently skips the LLM tier in that case (verdict cascades to `none`).
31
+ */
32
+ export async function buildIntegrationLLMPKCallback(contextUser) {
33
+ try {
34
+ await AIEngine.Instance.Config(false, contextUser);
35
+ }
36
+ catch (err) {
37
+ LogError(`[IntegrationLLMPKCallback] AIEngine.Config failed; LLM PK tier disabled: ${err instanceof Error ? err.message : err}`);
38
+ return null;
39
+ }
40
+ const models = AIEngine.Instance.LanguageModels.filter(m => m.IsActive === true);
41
+ if (models.length === 0) {
42
+ LogStatus(`[IntegrationLLMPKCallback] No active language model registered; LLM PK tier disabled.`);
43
+ return null;
44
+ }
45
+ // Highest PowerRank wins (or first if rank not set). The classifier doesn't
46
+ // need a frontier model — a cheap, fast chat model is perfectly capable of
47
+ // "given these field names + types, which is the PK?" Sort descending so
48
+ // priority-marked models surface first.
49
+ const sorted = [...models].sort((a, b) => (b.PowerRank ?? 0) - (a.PowerRank ?? 0));
50
+ const model = sorted[0];
51
+ const driverClass = model.DriverClass;
52
+ const apiName = model.APINameOrName;
53
+ if (!driverClass) {
54
+ LogStatus(`[IntegrationLLMPKCallback] Selected model "${model.Name}" has no DriverClass; LLM PK tier disabled.`);
55
+ return null;
56
+ }
57
+ const apiKey = GetAIAPIKeyGlobal(driverClass);
58
+ if (!apiKey) {
59
+ LogStatus(`[IntegrationLLMPKCallback] No API key registered for driver "${driverClass}"; LLM PK tier disabled.`);
60
+ return null;
61
+ }
62
+ const llm = MJGlobal.Instance.ClassFactory.CreateInstance(BaseLLM, driverClass, apiKey);
63
+ if (!llm) {
64
+ LogStatus(`[IntegrationLLMPKCallback] ClassFactory could not instantiate BaseLLM driver "${driverClass}"; LLM PK tier disabled.`);
65
+ return null;
66
+ }
67
+ LogStatus(`[IntegrationLLMPKCallback] LLM PK tier active using ${driverClass} / ${apiName}.`);
68
+ return async function llmPKInference(prompt) {
69
+ const systemMsg = `You are a database schema expert. Given a table's field list (and optional sample rows), ` +
70
+ `identify the single field most likely to be the primary key. ` +
71
+ `A primary key is unique, non-null, and immutable. ` +
72
+ `Common patterns: an "Id"/"<TableName>Id"/"UUID"/"GUID" field, ` +
73
+ `a system-generated identifier, or an int/long that's required + read-only + unique. ` +
74
+ `If no field plausibly qualifies (e.g. all fields are descriptive text, the table looks like a view or value list), ` +
75
+ `return nominee=null. NEVER guess a non-existent field name.`;
76
+ const userMsg = `Table: ${prompt.objectName}\n` +
77
+ `Fields (${prompt.fields.length}):\n` +
78
+ prompt.fields
79
+ .map(f => ` - ${f.name}` +
80
+ `${f.type ? ` (${f.type})` : ''}` +
81
+ `${f.length != null ? ` length=${f.length}` : ''}` +
82
+ `${f.isUnique ? ' UNIQUE' : ''}`)
83
+ .join('\n') +
84
+ (prompt.sampleSnippet
85
+ ? `\n\nSample rows (JSON, may be truncated):\n${prompt.sampleSnippet}`
86
+ : '') +
87
+ `\n\nReturn STRICT JSON ONLY with this exact shape:\n` +
88
+ `{"nominee": "<field-name-or-null>", "confidence": <0..1>, "reason": "<one-line>"}`;
89
+ const params = {
90
+ model: apiName,
91
+ messages: [
92
+ { role: 'system', content: systemMsg },
93
+ { role: 'user', content: userMsg },
94
+ ],
95
+ temperature: 0.1,
96
+ responseFormat: 'JSON',
97
+ };
98
+ try {
99
+ const result = await llm.ChatCompletion(params);
100
+ if (!result.success) {
101
+ LogStatus(`[IntegrationLLMPKCallback] LLM call for "${prompt.objectName}" failed: ${result.errorMessage}`);
102
+ return { nominee: null, confidence: 0, reason: `LLM call failed: ${result.errorMessage ?? 'unknown'}` };
103
+ }
104
+ const content = result.data.choices?.[0]?.message?.content;
105
+ if (!content) {
106
+ return { nominee: null, confidence: 0, reason: 'LLM returned no content.' };
107
+ }
108
+ const parsed = JSON.parse(content);
109
+ const nominee = parsed.nominee && prompt.fields.some(f => f.name === parsed.nominee)
110
+ ? parsed.nominee
111
+ : null;
112
+ const confidence = typeof parsed.confidence === 'number' ? Math.max(0, Math.min(1, parsed.confidence)) : 0;
113
+ const reason = typeof parsed.reason === 'string' ? parsed.reason : 'LLM verdict.';
114
+ return { nominee, confidence, reason };
115
+ }
116
+ catch (err) {
117
+ const msg = err instanceof Error ? err.message : String(err);
118
+ LogStatus(`[IntegrationLLMPKCallback] LLM call threw for "${prompt.objectName}": ${msg}`);
119
+ return { nominee: null, confidence: 0, reason: `Exception during LLM inference: ${msg}` };
120
+ }
121
+ };
122
+ }
123
+ //# sourceMappingURL=IntegrationLLMPKCallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrationLLMPKCallback.js","sourceRoot":"","sources":["../../src/custom/IntegrationLLMPKCallback.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MJAIPromptRunEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIPromptRunEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,iBAAiB,EAAkD,MAAM,sBAAsB,CAAC;AAErH,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAG3E;;;;;;GAMG;AACH,qBACa,yBAA0B,SAAQ,2BAA2B;IAEtE;;OAEG;IACY,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IA6BlE;;;OAGG;IACH,SAAS,CAAC,mBAAmB,IAAI,OAAO;IAkCxC;;OAEG;cACa,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IA6DpD;;OAEG;cACa,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBxD;;;;OAIG;IACU,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BlD;;;;OAIG;IACH,IAAW,cAAc,CAAC,KAAK,EAAE,MAAM,EAGtC;IAED,IAAW,cAAc,IAAI,MAAM,CAElC;IAED;;;;OAIG;IACH,IAAW,IAAI,CAAC,KAAK,EAAE,MAAM,EAG5B;IAED,IAAW,IAAI,IAAI,MAAM,CAExB;IACD;;;;;OAKG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;CAKpC"}
1
+ {"version":3,"file":"MJAIPromptRunEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIPromptRunEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,iBAAiB,EAAkD,MAAM,sBAAsB,CAAC;AAErH,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAG3E;;;;;;GAMG;AACH,qBACa,yBAA0B,SAAQ,2BAA2B;IAEtE;;OAEG;IACY,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IA6BlE;;;OAGG;IACH,SAAS,CAAC,mBAAmB,IAAI,OAAO;IAuCxC;;OAEG;cACa,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqEpD;;OAEG;cACa,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBxD;;;;OAIG;IACU,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BlD;;;;OAIG;IACH,IAAW,cAAc,CAAC,KAAK,EAAE,MAAM,EAGtC;IAED,IAAW,cAAc,IAAI,MAAM,CAElC;IAED;;;;OAIG;IACH,IAAW,IAAI,CAAC,KAAK,EAAE,MAAM,EAG5B;IAED,IAAW,IAAI,IAAI,MAAM,CAExB;IACD;;;;;OAKG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;CAKpC"}
@@ -62,9 +62,13 @@ let MJAIPromptRunEntityServer = class MJAIPromptRunEntityServer extends MJAIProm
62
62
  if (this.Cost != null && this.Cost > 0) {
63
63
  return false;
64
64
  }
65
- // Must have token usage to calculate (at least one token field > 0)
66
- if (!this.TokensPrompt || !this.TokensCompletion ||
67
- (this.TokensPrompt <= 0 && this.TokensCompletion <= 0)) {
65
+ // Must have token usage to calculate (at least one input or output token > 0). Input is the
66
+ // TOTAL input the provider processed: net-new (TokensPrompt) + cache reads + cache writes.
67
+ // A heavily-cached call can have TokensPrompt === 0 yet still incur input cost via cache
68
+ // tokens, so we gate on the total rather than net-new alone.
69
+ const totalInputTokens = (this.TokensPrompt ?? 0) + (this.TokensCacheRead ?? 0) + (this.TokensCacheWrite ?? 0);
70
+ const totalCompletionTokens = this.TokensCompletion ?? 0;
71
+ if (totalInputTokens <= 0 && totalCompletionTokens <= 0) {
68
72
  return false;
69
73
  }
70
74
  // Must have model and vendor information
@@ -99,7 +103,13 @@ let MJAIPromptRunEntityServer = class MJAIPromptRunEntityServer extends MJAIProm
99
103
  LogError(`Failed to create price calculator for driver class: ${priceUnitType.DriverClass}`);
100
104
  return;
101
105
  }
102
- const normalizedCost = priceCalculator.CalculateNormalizedCost(activeCost, this.TokensPrompt, this.TokensCompletion);
106
+ // Price each input bucket at its own rate: uncached/net-new (TokensPrompt) at the
107
+ // standard input rate, cache reads/writes at CacheReadPricePerUnit/CacheWritePricePerUnit
108
+ // when the cost row records them. When those cache rates are NULL the calculator falls
109
+ // back to the input rate, so the result is identical to the prior single-bucket behavior
110
+ // for models without cache pricing — while models that DO have cache rates get the
111
+ // (usually much cheaper) cached-token cost instead of being billed as full input.
112
+ const normalizedCost = priceCalculator.CalculateNormalizedCostWithCache(activeCost, this.TokensPrompt ?? 0, this.TokensCacheRead ?? 0, this.TokensCacheWrite ?? 0, this.TokensCompletion ?? 0);
103
113
  // Set the cost fields
104
114
  this.Cost = normalizedCost;
105
115
  this.CostCurrency = activeCost.Currency;
@@ -1 +1 @@
1
- {"version":3,"file":"MJAIPromptRunEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJAIPromptRunEntityServer.server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MJAIPromptRunEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJAIPromptRunEntityServer.server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import { EntitySaveOptions } from '@memberjunction/core';
2
+ import { MJCompanyIntegrationEntity } from '@memberjunction/core-entities';
3
+ /**
4
+ * Server-side extension of MJCompanyIntegrationEntity that:
5
+ *
6
+ * Awaits `IntegrationConnectorCreationPipeline.Run()` whenever `IsActive`
7
+ * transitions `false → true` on a successful save. This is the wizard-Finish
8
+ * trigger point — when an operator activates a connection (via the wizard,
9
+ * the Update mutation, direct entity edit, or any other code path that saves
10
+ * IsActive=true on a previously-inactive row), the pipeline runs:
11
+ *
12
+ * 1. TestConnection — verify credentials still pass
13
+ * 2. IntrospectSchema — live describe across all objects
14
+ * 3. PersistDiscoveredSchema — overlay-aware upsert (Declared/Discovered/Custom)
15
+ * 4. SoftPKClassifier — 4-tier cascade for IOs lacking explicit PK
16
+ * 5. Metadata.Refresh — engine cache picks up the new rows
17
+ *
18
+ * The pipeline emits structured JSON events to the MJAPI log via
19
+ * `IntegrationProgressEmitter` so operators can watch progress in real time:
20
+ * `tail -f /tmp/mjapi.log | grep '"event":"\(introspect\|persist\|pk\|entity\|stage\|run\)\.'`
21
+ *
22
+ * PER-RUN JSONL ARTIFACTS land at:
23
+ * `<cwd>/logs/integration-runs/<runID>/{manifest,progress,result}.json`
24
+ *
25
+ * SYNCHRONOUS EXECUTION. The pipeline now AWAITS so the wizard's Finish
26
+ * button (which does `ci.IsActive=true; ci.Save()`) stays in its "Saving..."
27
+ * state until the schema refresh completes. HubSpot ~130 objects × 8-way
28
+ * parallel describe lands ~10-30s; that becomes the wizard's perceived load
29
+ * time — which is the correct UX (the wizard is, in fact, updating).
30
+ *
31
+ * IDEMPOTENT BY DESIGN. The pipeline overlays existing rows; the transition
32
+ * guard (was-false → now-true) keeps repeat saves (renames, config tweaks)
33
+ * from re-firing.
34
+ *
35
+ * FAILURE ISOLATION. Pipeline failure does NOT undo the Save. Operator can
36
+ * re-run via the standalone `IntegrationRefreshConnectorSchema` GraphQL
37
+ * mutation if needed. The save still returns true even on pipeline failure.
38
+ *
39
+ * ───────────────────────────────────────────────────────────────────────────
40
+ * ALGORITHM GAPS — DEFERRED FOR FOLLOWUP PR (not Phase 0 PR1)
41
+ * ───────────────────────────────────────────────────────────────────────────
42
+ *
43
+ * Phase 0 ships the OVERLAY-ADD half of the algorithm: discovered fields
44
+ * the IO doesn't already know about get added with `MetadataSource='Discovered'`.
45
+ * The full canonical algorithm has more steps; (a) and (d) remain genuine
46
+ * follow-up deferrals because they require additional schema + UI wiring,
47
+ * while (b) is now IMPLEMENTED and (c) is largely mooted (see below):
48
+ *
49
+ * (a) DECLARED-BUT-MISSING-IN-INSTANCE → DEPRECATED. When the Declared
50
+ * catalog has a field for table X, but THIS customer's live introspect
51
+ * doesn't return that field, mark it deprecated FOR THIS COMPANY
52
+ * INTEGRATION only (other tenants still see Active). This is per-
53
+ * instance state — needs either a new junction (CompanyIntegration ×
54
+ * IntegrationObjectField with Status) or a Configuration JSON listing
55
+ * on CompanyIntegration. Currently NOT implemented: existing IOFs
56
+ * stay Active even when missing from the live instance.
57
+ *
58
+ * (b) AI PK INFERENCE for custom tables. IMPLEMENTED. When a Discovered
59
+ * table has no explicit PK marker, the SoftPKClassifier runs
60
+ * universal-convention → naming → statistical → LLM. The LLM tier's
61
+ * callback IS wired here: `buildIntegrationLLMPKCallback(user)` is built
62
+ * below and passed into the pipeline as `LLMInference`, so when explicit
63
+ * + naming + statistical all fail, an LLM proposes a (potentially
64
+ * composite) PK from the field schema + sample rows. (The callback can
65
+ * still return undefined if no AI model resolves, in which case the LLM
66
+ * tier degrades to a no-op — but the wiring itself is no longer a gap.)
67
+ *
68
+ * (c) DROP IF NO PK DETERMINABLE. Largely MOOTED. The original concern was
69
+ * that an IO ending with `Confident=false` would persist as a PK-less row
70
+ * polluting the catalog, so canonical behavior would DELETE it. With
71
+ * SoftPKClassifier's now-default synthetic-PK fallback, almost nothing
72
+ * reaches `Confident=false` — a synthetic identifier is emitted as the
73
+ * last resort — so the drop-if-no-PK path is rarely if ever exercised.
74
+ * Not implemented as an explicit delete, but no longer a practical gap.
75
+ *
76
+ * (d) DETAILED PROGRESS UI in the wizard. Today the wizard shows a
77
+ * generic "Saving..." spinner while the pipeline runs. Operators
78
+ * want plain-English step indicators ("Discovering tables...",
79
+ * "Analyzing 47 fields for Contacts...", "Inferring primary key
80
+ * for custom_quote_item..."). Needs an Angular wizard update +
81
+ * either SSE/WebSocket progress streaming or polling. Pre-existing
82
+ * Angular dashboards build issues on this branch block that work
83
+ * (out of Phase 0 PR scope).
84
+ */
85
+ export declare class MJCompanyIntegrationEntityServer extends MJCompanyIntegrationEntity {
86
+ Save(options?: EntitySaveOptions): Promise<boolean>;
87
+ /**
88
+ * Resolves the registered connector for this CompanyIntegration, runs the
89
+ * Phase 0 v5.39.x pipeline, and refreshes the in-memory caches so the next
90
+ * read sees the newly-persisted IO/IOF rows.
91
+ */
92
+ private fireSchemaRefreshPipeline;
93
+ }
94
+ //# sourceMappingURL=MJCompanyIntegrationEntityServer.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJCompanyIntegrationEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJCompanyIntegrationEntityServer.server.ts"],"names":[],"mappings":"AACA,OAAO,EAEH,iBAAiB,EAOpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,0BAA0B,EAAuB,MAAM,+BAA+B,CAAC;AAQhG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AACH,qBACa,gCAAiC,SAAQ,0BAA0B;IACtD,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAiCzE;;;;OAIG;YACW,yBAAyB;CA0E1C"}
@@ -0,0 +1,207 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { RegisterClass } from '@memberjunction/global';
8
+ import { BaseEntity, LogError, LogStatus, Metadata, RunView, } from '@memberjunction/core';
9
+ import { MJCompanyIntegrationEntity } from '@memberjunction/core-entities';
10
+ import { IntegrationConnectorCreationPipeline, IntegrationEngine, ConnectorFactory, } from '@memberjunction/integration-engine';
11
+ import { buildIntegrationLLMPKCallback } from './IntegrationLLMPKCallback.js';
12
+ /**
13
+ * Server-side extension of MJCompanyIntegrationEntity that:
14
+ *
15
+ * Awaits `IntegrationConnectorCreationPipeline.Run()` whenever `IsActive`
16
+ * transitions `false → true` on a successful save. This is the wizard-Finish
17
+ * trigger point — when an operator activates a connection (via the wizard,
18
+ * the Update mutation, direct entity edit, or any other code path that saves
19
+ * IsActive=true on a previously-inactive row), the pipeline runs:
20
+ *
21
+ * 1. TestConnection — verify credentials still pass
22
+ * 2. IntrospectSchema — live describe across all objects
23
+ * 3. PersistDiscoveredSchema — overlay-aware upsert (Declared/Discovered/Custom)
24
+ * 4. SoftPKClassifier — 4-tier cascade for IOs lacking explicit PK
25
+ * 5. Metadata.Refresh — engine cache picks up the new rows
26
+ *
27
+ * The pipeline emits structured JSON events to the MJAPI log via
28
+ * `IntegrationProgressEmitter` so operators can watch progress in real time:
29
+ * `tail -f /tmp/mjapi.log | grep '"event":"\(introspect\|persist\|pk\|entity\|stage\|run\)\.'`
30
+ *
31
+ * PER-RUN JSONL ARTIFACTS land at:
32
+ * `<cwd>/logs/integration-runs/<runID>/{manifest,progress,result}.json`
33
+ *
34
+ * SYNCHRONOUS EXECUTION. The pipeline now AWAITS so the wizard's Finish
35
+ * button (which does `ci.IsActive=true; ci.Save()`) stays in its "Saving..."
36
+ * state until the schema refresh completes. HubSpot ~130 objects × 8-way
37
+ * parallel describe lands ~10-30s; that becomes the wizard's perceived load
38
+ * time — which is the correct UX (the wizard is, in fact, updating).
39
+ *
40
+ * IDEMPOTENT BY DESIGN. The pipeline overlays existing rows; the transition
41
+ * guard (was-false → now-true) keeps repeat saves (renames, config tweaks)
42
+ * from re-firing.
43
+ *
44
+ * FAILURE ISOLATION. Pipeline failure does NOT undo the Save. Operator can
45
+ * re-run via the standalone `IntegrationRefreshConnectorSchema` GraphQL
46
+ * mutation if needed. The save still returns true even on pipeline failure.
47
+ *
48
+ * ───────────────────────────────────────────────────────────────────────────
49
+ * ALGORITHM GAPS — DEFERRED FOR FOLLOWUP PR (not Phase 0 PR1)
50
+ * ───────────────────────────────────────────────────────────────────────────
51
+ *
52
+ * Phase 0 ships the OVERLAY-ADD half of the algorithm: discovered fields
53
+ * the IO doesn't already know about get added with `MetadataSource='Discovered'`.
54
+ * The full canonical algorithm has more steps; (a) and (d) remain genuine
55
+ * follow-up deferrals because they require additional schema + UI wiring,
56
+ * while (b) is now IMPLEMENTED and (c) is largely mooted (see below):
57
+ *
58
+ * (a) DECLARED-BUT-MISSING-IN-INSTANCE → DEPRECATED. When the Declared
59
+ * catalog has a field for table X, but THIS customer's live introspect
60
+ * doesn't return that field, mark it deprecated FOR THIS COMPANY
61
+ * INTEGRATION only (other tenants still see Active). This is per-
62
+ * instance state — needs either a new junction (CompanyIntegration ×
63
+ * IntegrationObjectField with Status) or a Configuration JSON listing
64
+ * on CompanyIntegration. Currently NOT implemented: existing IOFs
65
+ * stay Active even when missing from the live instance.
66
+ *
67
+ * (b) AI PK INFERENCE for custom tables. IMPLEMENTED. When a Discovered
68
+ * table has no explicit PK marker, the SoftPKClassifier runs
69
+ * universal-convention → naming → statistical → LLM. The LLM tier's
70
+ * callback IS wired here: `buildIntegrationLLMPKCallback(user)` is built
71
+ * below and passed into the pipeline as `LLMInference`, so when explicit
72
+ * + naming + statistical all fail, an LLM proposes a (potentially
73
+ * composite) PK from the field schema + sample rows. (The callback can
74
+ * still return undefined if no AI model resolves, in which case the LLM
75
+ * tier degrades to a no-op — but the wiring itself is no longer a gap.)
76
+ *
77
+ * (c) DROP IF NO PK DETERMINABLE. Largely MOOTED. The original concern was
78
+ * that an IO ending with `Confident=false` would persist as a PK-less row
79
+ * polluting the catalog, so canonical behavior would DELETE it. With
80
+ * SoftPKClassifier's now-default synthetic-PK fallback, almost nothing
81
+ * reaches `Confident=false` — a synthetic identifier is emitted as the
82
+ * last resort — so the drop-if-no-PK path is rarely if ever exercised.
83
+ * Not implemented as an explicit delete, but no longer a practical gap.
84
+ *
85
+ * (d) DETAILED PROGRESS UI in the wizard. Today the wizard shows a
86
+ * generic "Saving..." spinner while the pipeline runs. Operators
87
+ * want plain-English step indicators ("Discovering tables...",
88
+ * "Analyzing 47 fields for Contacts...", "Inferring primary key
89
+ * for custom_quote_item..."). Needs an Angular wizard update +
90
+ * either SSE/WebSocket progress streaming or polling. Pre-existing
91
+ * Angular dashboards build issues on this branch block that work
92
+ * (out of Phase 0 PR scope).
93
+ */
94
+ let MJCompanyIntegrationEntityServer = class MJCompanyIntegrationEntityServer extends MJCompanyIntegrationEntity {
95
+ async Save(options) {
96
+ // Snapshot the pre-save IsActive value so we can detect the transition
97
+ // AFTER `super.Save()` returns successfully. When the row is new
98
+ // (`!this.IsSaved`), prior is `false` by default — the framework's
99
+ // IsActive defaults to false for new rows and the wizard explicitly
100
+ // flips it to true on Finish.
101
+ const priorIsActive = this.IsSaved
102
+ ? !!this.GetFieldByName('IsActive').OldValue
103
+ : false;
104
+ const nowIsActive = !!this.IsActive;
105
+ const transitionedToActive = !priorIsActive && nowIsActive;
106
+ const saved = await super.Save(options);
107
+ if (!saved)
108
+ return false;
109
+ if (transitionedToActive) {
110
+ // AWAIT the pipeline — the wizard's Finish button stays in its
111
+ // "Saving…" state until the schema refresh completes, so the
112
+ // operator sees real visual feedback during the actual work
113
+ // instead of an instant fake-done. Pipeline failure is logged
114
+ // and surfaced via LatestResult but does NOT undo the activation
115
+ // — the connection is still saved; only the schema discovery
116
+ // failed and can be retried via IntegrationRefreshConnectorSchema.
117
+ try {
118
+ await this.fireSchemaRefreshPipeline();
119
+ }
120
+ catch (err) {
121
+ LogError(`[MJCompanyIntegrationEntityServer] Schema refresh pipeline error (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
122
+ }
123
+ }
124
+ return true;
125
+ }
126
+ /**
127
+ * Resolves the registered connector for this CompanyIntegration, runs the
128
+ * Phase 0 v5.39.x pipeline, and refreshes the in-memory caches so the next
129
+ * read sees the newly-persisted IO/IOF rows.
130
+ */
131
+ async fireSchemaRefreshPipeline() {
132
+ const user = this.ContextCurrentUser;
133
+ if (!user) {
134
+ LogStatus(`[MJCompanyIntegrationEntityServer] Schema refresh skipped for ${this.ID}: no ContextCurrentUser on entity`);
135
+ return;
136
+ }
137
+ // `ProviderToUse` is typed `IEntityDataProvider`; the pipeline/engine APIs
138
+ // want the broader `IMetadataProvider`. The concrete server provider
139
+ // implements both, but the two interfaces don't structurally overlap, so a
140
+ // single `as` won't compile — narrow to `as IMetadataProvider` via unknown.
141
+ const provider = this.ProviderToUse;
142
+ LogStatus(`[MJCompanyIntegrationEntityServer] IsActive false→true detected on ${this.Integration ?? this.ID} (${this.ID}); firing schema refresh pipeline.`);
143
+ // Make sure the IntegrationEngine cache is hot so ConnectorFactory.Resolve
144
+ // can look up the registered class for this Integration.
145
+ await IntegrationEngine.Instance.Config(false, user, provider);
146
+ // Load the parent Integration row to feed ConnectorFactory.Resolve.
147
+ const rv = new RunView();
148
+ const integResult = await rv.RunView({
149
+ EntityName: 'MJ: Integrations',
150
+ ExtraFilter: `ID='${this.IntegrationID}'`,
151
+ ResultType: 'entity_object',
152
+ MaxRows: 1,
153
+ }, user);
154
+ const integration = integResult.Success ? integResult.Results[0] : undefined;
155
+ if (!integration) {
156
+ LogError(`[MJCompanyIntegrationEntityServer] Integration row not found for IntegrationID=${this.IntegrationID}; pipeline skipped.`);
157
+ return;
158
+ }
159
+ let connector;
160
+ try {
161
+ connector = ConnectorFactory.Resolve(integration);
162
+ }
163
+ catch (resolveErr) {
164
+ LogError(`[MJCompanyIntegrationEntityServer] No connector registered for ClassName=${integration.ClassName}: ${resolveErr instanceof Error ? resolveErr.message : String(resolveErr)}`);
165
+ return;
166
+ }
167
+ // Build the LLM PK callback so SoftPKClassifier's LLM tier can run
168
+ // (the 4th tier in the cascade — universal → naming → statistical → LLM
169
+ // → synthetic). Without this callback the LLM tier is silently skipped
170
+ // and any custom table without an obvious convention/heuristic match
171
+ // falls through to the synthetic-PK fallback (see StagePKClassify in
172
+ // IntegrationConnectorCreationPipeline.ts); wiring it gives such tables
173
+ // a chance at a more meaningful AI-proposed key first.
174
+ const llmInference = await buildIntegrationLLMPKCallback(user);
175
+ // The pipeline takes a fully-typed CompanyIntegration; this class extends
176
+ // MJCompanyIntegrationEntity, so `this` satisfies the contract directly.
177
+ const pipeline = new IntegrationConnectorCreationPipeline();
178
+ const result = await pipeline.Run({
179
+ Connector: connector,
180
+ CompanyIntegration: this,
181
+ ContextUser: user,
182
+ Provider: provider,
183
+ ConsoleMirror: true,
184
+ TriggerType: 'Manual',
185
+ LLMInference: llmInference ?? undefined,
186
+ });
187
+ // Pipeline persists IO/IOF rows — refresh metadata caches so subsequent
188
+ // reads see them without an MJAPI restart.
189
+ try {
190
+ await (provider ?? new Metadata()).Refresh();
191
+ }
192
+ catch { /* best-effort */ }
193
+ try {
194
+ await IntegrationEngine.Instance.Config(true, user, provider);
195
+ }
196
+ catch { /* best-effort */ }
197
+ LogStatus(`[MJCompanyIntegrationEntityServer] Schema refresh complete for ${this.Integration ?? this.ID}: ` +
198
+ `${result.PersistResult?.ObjectsCreated ?? 0} created, ${result.PersistResult?.ObjectsUpdated ?? 0} updated, ` +
199
+ `${result.PersistResult?.FieldsCreated ?? 0} fields created, ${result.PersistResult?.FieldsUpdated ?? 0} fields updated, ` +
200
+ `${result.UnresolvedObjects.length} IOs PK-unresolved (deferred for additionalSchemaInfo authoring).`);
201
+ }
202
+ };
203
+ MJCompanyIntegrationEntityServer = __decorate([
204
+ RegisterClass(BaseEntity, 'MJ: Company Integrations')
205
+ ], MJCompanyIntegrationEntityServer);
206
+ export { MJCompanyIntegrationEntityServer };
207
+ //# sourceMappingURL=MJCompanyIntegrationEntityServer.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJCompanyIntegrationEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJCompanyIntegrationEntityServer.server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { EntitySaveOptions, IMetadataProvider, TransactionGroupBase } from "@memberjunction/core";
2
+ import { MJEntityDocumentEntityExtended } from "@memberjunction/ai-core-plus";
3
+ import { MJTemplateEntity } from "@memberjunction/core-entities";
4
+ /**
5
+ * Server-side subclass for `MJ: Entity Documents` that mirrors the
6
+ * `MJAIPromptEntityServer` template-write pattern: when `TemplateText` (the
7
+ * virtual property on {@link MJEntityDocumentEntityExtended}) is set and the
8
+ * entity is saved, this class creates or updates the linked Template + primary
9
+ * TemplateContent records, then stamps the new `TemplateID` onto the
10
+ * EntityDocument before delegating to `super.Save()`.
11
+ *
12
+ * **Why this exists.** Per `mj-sync`, the `Template` virtual field on the
13
+ * `EntityDocument` view is read-only (a denormalized name from the FK), so a
14
+ * sync push can't write template body via the view. Surfacing a writable
15
+ * `TemplateText` virtual property plus this Save() hook is the same trick the
16
+ * AI Prompt entity uses, and it lets entity-document metadata files reference
17
+ * `@file:templates/foo.njk` exactly like prompts do.
18
+ */
19
+ export declare class MJEntityDocumentEntityServer extends MJEntityDocumentEntityExtended {
20
+ private static _templateContentTypeID;
21
+ /**
22
+ * The TemplateContent.TypeID used for newly-created TemplateContents linked
23
+ * to an EntityDocument. Resolved once per process from the "Text" content
24
+ * type and cached. Settable up front if a host wants to force a different
25
+ * content type.
26
+ */
27
+ static get TemplateContentTypeID(): string | null;
28
+ static set TemplateContentTypeID(value: string | null);
29
+ private static _rootTemplateCategoryID;
30
+ /**
31
+ * Root template-category ID used to host auto-created Templates for
32
+ * EntityDocuments. Resolved once per process by name lookup
33
+ * ("MJ: Entity Documents") and created on demand if missing.
34
+ */
35
+ static get RootTemplateCategoryID(): string | null;
36
+ static set RootTemplateCategoryID(value: string | null);
37
+ /**
38
+ * Resolve the root category for auto-created EntityDocument templates.
39
+ * Checks the in-memory cache first; falls back to a Name lookup; finally
40
+ * creates the category if it doesn't exist yet. Mirrors the AI Prompt
41
+ * pattern so existing operators recognize it.
42
+ */
43
+ protected getOrCreateRootTemplateCategoryID(): Promise<string>;
44
+ /** Create the root template category when one doesn't exist yet. */
45
+ protected createRootTemplateCategory(name: string): Promise<string>;
46
+ /**
47
+ * Save() override — same shape as `MJAIPromptEntityServer.Save()`:
48
+ *
49
+ * 1. If `TemplateID` is null and `TemplateText` is non-empty, create
50
+ * a new Template + TemplateContent and stamp the EntityDocument's
51
+ * `TemplateID`.
52
+ * 2. If `TemplateID` is set and `TemplateText` has changed, update the
53
+ * linked TemplateContent in place.
54
+ * 3. Then call `super.Save()` and, on success, sync
55
+ * `_originalTemplateText` so subsequent dirty-checks are accurate.
56
+ *
57
+ * Any failure in the template-write path short-circuits the save with a
58
+ * recorded `BaseEntityResult` so callers see the same failure shape they
59
+ * get from a base-entity validation error.
60
+ */
61
+ Save(options?: EntitySaveOptions): Promise<boolean>;
62
+ /** Update the linked Template's primary TemplateContent in place. */
63
+ protected UpdateLinkedTemplateContents(md: IMetadataProvider, tg?: TransactionGroupBase): Promise<boolean>;
64
+ /** Create a new Template + primary TemplateContent linked to this EntityDocument. */
65
+ protected CreateLinkedTemplateAndTemplateContents(md: IMetadataProvider): Promise<MJTemplateEntity | null>;
66
+ /** Resolve the "Text" TemplateContentType ID once per process and cache it. */
67
+ protected getTemplateContentTypeID(): Promise<string>;
68
+ }
69
+ //# sourceMappingURL=MJEntityDocumentEntityServer.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJEntityDocumentEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJEntityDocumentEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,iBAAiB,EAAE,iBAAiB,EAAgC,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE9J,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAkF,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjJ;;;;;;;;;;;;;;GAcG;AACH,qBACa,4BAA6B,SAAQ,8BAA8B;IAC5E,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAuB;IAC5D;;;;;OAKG;IACH,WAAkB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAEvD;IACD,WAAkB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAE3D;IAED,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAuB;IAC7D;;;;OAIG;IACH,WAAkB,sBAAsB,IAAI,MAAM,GAAG,IAAI,CAExD;IACD,WAAkB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAE5D;IAED;;;;;OAKG;cACa,iCAAiC,IAAI,OAAO,CAAC,MAAM,CAAC;IAuBpE,oEAAoE;cACpD,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBzE;;;;;;;;;;;;;;OAcG;IACY,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoClE,qEAAqE;cACrD,4BAA4B,CAAC,EAAE,EAAE,iBAAiB,EAAE,EAAE,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAwChH,qFAAqF;cACrE,uCAAuC,CAAC,EAAE,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAoChH,+EAA+E;cAC/D,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC;CAgB9D"}