@memberjunction/db-auto-doc 6.2.0-edge.4 → 6.2.0-edge.6

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 (183) hide show
  1. package/README.md +105 -0
  2. package/dist/api/DBAutoDocAPI.d.ts +2 -0
  3. package/dist/api/DBAutoDocAPI.d.ts.map +1 -1
  4. package/dist/api/DBAutoDocAPI.js +2 -1
  5. package/dist/api/DBAutoDocAPI.js.map +1 -1
  6. package/dist/commands/analyze.d.ts +1 -0
  7. package/dist/commands/analyze.d.ts.map +1 -1
  8. package/dist/commands/analyze.js +6 -0
  9. package/dist/commands/analyze.js.map +1 -1
  10. package/dist/commands/export.d.ts +28 -19
  11. package/dist/commands/export.d.ts.map +1 -1
  12. package/dist/commands/export.js +91 -12
  13. package/dist/commands/export.js.map +1 -1
  14. package/dist/core/AnalysisEngine.d.ts +39 -6
  15. package/dist/core/AnalysisEngine.d.ts.map +1 -1
  16. package/dist/core/AnalysisEngine.js +144 -50
  17. package/dist/core/AnalysisEngine.js.map +1 -1
  18. package/dist/core/AnalysisOrchestrator.d.ts +20 -1
  19. package/dist/core/AnalysisOrchestrator.d.ts.map +1 -1
  20. package/dist/core/AnalysisOrchestrator.js +144 -28
  21. package/dist/core/AnalysisOrchestrator.js.map +1 -1
  22. package/dist/core/PKProposalGate.d.ts +22 -0
  23. package/dist/core/PKProposalGate.d.ts.map +1 -0
  24. package/dist/core/PKProposalGate.js +52 -0
  25. package/dist/core/PKProposalGate.js.map +1 -0
  26. package/dist/database/Database.d.ts +8 -0
  27. package/dist/database/Database.d.ts.map +1 -1
  28. package/dist/database/Database.js +23 -1
  29. package/dist/database/Database.js.map +1 -1
  30. package/dist/discovery/ColumnNormalizer.d.ts +31 -0
  31. package/dist/discovery/ColumnNormalizer.d.ts.map +1 -1
  32. package/dist/discovery/ColumnNormalizer.js +68 -2
  33. package/dist/discovery/ColumnNormalizer.js.map +1 -1
  34. package/dist/discovery/Composer.d.ts +33 -2
  35. package/dist/discovery/Composer.d.ts.map +1 -1
  36. package/dist/discovery/Composer.js +126 -5
  37. package/dist/discovery/Composer.js.map +1 -1
  38. package/dist/discovery/DiscoveryEngine.d.ts +3 -0
  39. package/dist/discovery/DiscoveryEngine.d.ts.map +1 -1
  40. package/dist/discovery/DiscoveryEngine.js +1 -1
  41. package/dist/discovery/DiscoveryEngine.js.map +1 -1
  42. package/dist/discovery/EmbeddingProvider.d.ts +6 -1
  43. package/dist/discovery/EmbeddingProvider.d.ts.map +1 -1
  44. package/dist/discovery/EmbeddingProvider.js +11 -1
  45. package/dist/discovery/EmbeddingProvider.js.map +1 -1
  46. package/dist/discovery/EnumCandidateGate.d.ts +19 -0
  47. package/dist/discovery/EnumCandidateGate.d.ts.map +1 -1
  48. package/dist/discovery/EnumCandidateGate.js +47 -5
  49. package/dist/discovery/EnumCandidateGate.js.map +1 -1
  50. package/dist/discovery/FKGraphWalker.d.ts +35 -0
  51. package/dist/discovery/FKGraphWalker.d.ts.map +1 -1
  52. package/dist/discovery/FKGraphWalker.js +113 -12
  53. package/dist/discovery/FKGraphWalker.js.map +1 -1
  54. package/dist/discovery/IndexKeyEvidence.d.ts +36 -0
  55. package/dist/discovery/IndexKeyEvidence.d.ts.map +1 -0
  56. package/dist/discovery/IndexKeyEvidence.js +42 -0
  57. package/dist/discovery/IndexKeyEvidence.js.map +1 -0
  58. package/dist/discovery/JoinProbe.d.ts +148 -0
  59. package/dist/discovery/JoinProbe.d.ts.map +1 -0
  60. package/dist/discovery/JoinProbe.js +233 -0
  61. package/dist/discovery/JoinProbe.js.map +1 -0
  62. package/dist/discovery/LLMDiscoveryValidator.d.ts +10 -1
  63. package/dist/discovery/LLMDiscoveryValidator.d.ts.map +1 -1
  64. package/dist/discovery/LLMDiscoveryValidator.js +44 -12
  65. package/dist/discovery/LLMDiscoveryValidator.js.map +1 -1
  66. package/dist/discovery/LLMSanityChecker.d.ts.map +1 -1
  67. package/dist/discovery/LLMSanityChecker.js +10 -1
  68. package/dist/discovery/LLMSanityChecker.js.map +1 -1
  69. package/dist/discovery/OrganicKeyDetector.d.ts +29 -1
  70. package/dist/discovery/OrganicKeyDetector.d.ts.map +1 -1
  71. package/dist/discovery/OrganicKeyDetector.js +34 -5
  72. package/dist/discovery/OrganicKeyDetector.js.map +1 -1
  73. package/dist/discovery/OrganicKeyTranslator.d.ts +24 -5
  74. package/dist/discovery/OrganicKeyTranslator.d.ts.map +1 -1
  75. package/dist/discovery/OrganicKeyTranslator.js +32 -14
  76. package/dist/discovery/OrganicKeyTranslator.js.map +1 -1
  77. package/dist/discovery/PKDetector.d.ts +9 -0
  78. package/dist/discovery/PKDetector.d.ts.map +1 -1
  79. package/dist/discovery/PKDetector.js +86 -8
  80. package/dist/discovery/PKDetector.js.map +1 -1
  81. package/dist/discovery/SemanticPhase.d.ts +25 -0
  82. package/dist/discovery/SemanticPhase.d.ts.map +1 -1
  83. package/dist/discovery/SemanticPhase.js +55 -11
  84. package/dist/discovery/SemanticPhase.js.map +1 -1
  85. package/dist/discovery/StructuralPhase.d.ts +27 -5
  86. package/dist/discovery/StructuralPhase.d.ts.map +1 -1
  87. package/dist/discovery/StructuralPhase.js +42 -9
  88. package/dist/discovery/StructuralPhase.js.map +1 -1
  89. package/dist/discovery/TransitiveBridgeDetector.d.ts +5 -1
  90. package/dist/discovery/TransitiveBridgeDetector.d.ts.map +1 -1
  91. package/dist/discovery/TransitiveBridgeDetector.js +25 -3
  92. package/dist/discovery/TransitiveBridgeDetector.js.map +1 -1
  93. package/dist/discovery/embedding-provider-default.d.ts +25 -0
  94. package/dist/discovery/embedding-provider-default.d.ts.map +1 -0
  95. package/dist/discovery/embedding-provider-default.js +47 -0
  96. package/dist/discovery/embedding-provider-default.js.map +1 -0
  97. package/dist/drivers/BaseAutoDocDriver.d.ts +63 -0
  98. package/dist/drivers/BaseAutoDocDriver.d.ts.map +1 -1
  99. package/dist/drivers/BaseAutoDocDriver.js +3 -5
  100. package/dist/drivers/BaseAutoDocDriver.js.map +1 -1
  101. package/dist/drivers/MySQLDriver.d.ts +21 -1
  102. package/dist/drivers/MySQLDriver.d.ts.map +1 -1
  103. package/dist/drivers/MySQLDriver.js +64 -0
  104. package/dist/drivers/MySQLDriver.js.map +1 -1
  105. package/dist/drivers/PostgreSQLDriver.d.ts +43 -2
  106. package/dist/drivers/PostgreSQLDriver.d.ts.map +1 -1
  107. package/dist/drivers/PostgreSQLDriver.js +132 -19
  108. package/dist/drivers/PostgreSQLDriver.js.map +1 -1
  109. package/dist/drivers/SQLServerDriver.d.ts +28 -1
  110. package/dist/drivers/SQLServerDriver.d.ts.map +1 -1
  111. package/dist/drivers/SQLServerDriver.js +108 -1
  112. package/dist/drivers/SQLServerDriver.js.map +1 -1
  113. package/dist/drivers/probeErrors.d.ts +30 -0
  114. package/dist/drivers/probeErrors.d.ts.map +1 -0
  115. package/dist/drivers/probeErrors.js +94 -0
  116. package/dist/drivers/probeErrors.js.map +1 -0
  117. package/dist/generators/AdditionalSchemaInfoGenerator.d.ts +34 -18
  118. package/dist/generators/AdditionalSchemaInfoGenerator.d.ts.map +1 -1
  119. package/dist/generators/AdditionalSchemaInfoGenerator.js +130 -8
  120. package/dist/generators/AdditionalSchemaInfoGenerator.js.map +1 -1
  121. package/dist/generators/ErdClusterGenerator.d.ts +44 -0
  122. package/dist/generators/ErdClusterGenerator.d.ts.map +1 -0
  123. package/dist/generators/ErdClusterGenerator.js +216 -0
  124. package/dist/generators/ErdClusterGenerator.js.map +1 -0
  125. package/dist/generators/ErdClusterer.d.ts +130 -0
  126. package/dist/generators/ErdClusterer.d.ts.map +1 -0
  127. package/dist/generators/ErdClusterer.js +308 -0
  128. package/dist/generators/ErdClusterer.js.map +1 -0
  129. package/dist/generators/HTMLGenerator.d.ts +6 -0
  130. package/dist/generators/HTMLGenerator.d.ts.map +1 -1
  131. package/dist/generators/HTMLGenerator.js +41 -6
  132. package/dist/generators/HTMLGenerator.js.map +1 -1
  133. package/dist/generators/MermaidGenerator.d.ts +3 -0
  134. package/dist/generators/MermaidGenerator.d.ts.map +1 -1
  135. package/dist/generators/MermaidGenerator.js +4 -0
  136. package/dist/generators/MermaidGenerator.js.map +1 -1
  137. package/dist/generators/index.d.ts +2 -0
  138. package/dist/generators/index.d.ts.map +1 -1
  139. package/dist/generators/index.js +2 -0
  140. package/dist/generators/index.js.map +1 -1
  141. package/dist/prompts/PromptEngine.d.ts.map +1 -1
  142. package/dist/prompts/PromptEngine.js +10 -1
  143. package/dist/prompts/PromptEngine.js.map +1 -1
  144. package/dist/types/analysis.d.ts +2 -0
  145. package/dist/types/analysis.d.ts.map +1 -1
  146. package/dist/types/config.d.ts +128 -4
  147. package/dist/types/config.d.ts.map +1 -1
  148. package/dist/types/config.js +7 -1
  149. package/dist/types/config.js.map +1 -1
  150. package/dist/types/discovery.d.ts +41 -0
  151. package/dist/types/discovery.d.ts.map +1 -1
  152. package/dist/types/state.d.ts +29 -0
  153. package/dist/types/state.d.ts.map +1 -1
  154. package/dist/utils/call-deadline.d.ts +43 -0
  155. package/dist/utils/call-deadline.d.ts.map +1 -0
  156. package/dist/utils/call-deadline.js +81 -0
  157. package/dist/utils/call-deadline.js.map +1 -0
  158. package/dist/utils/config-loader.d.ts +5 -0
  159. package/dist/utils/config-loader.d.ts.map +1 -1
  160. package/dist/utils/config-loader.js +37 -0
  161. package/dist/utils/config-loader.js.map +1 -1
  162. package/dist/utils/index-hints.d.ts +43 -0
  163. package/dist/utils/index-hints.d.ts.map +1 -0
  164. package/dist/utils/index-hints.js +80 -0
  165. package/dist/utils/index-hints.js.map +1 -0
  166. package/dist/utils/index.d.ts +2 -0
  167. package/dist/utils/index.d.ts.map +1 -1
  168. package/dist/utils/index.js +2 -0
  169. package/dist/utils/index.js.map +1 -1
  170. package/dist/utils/llm-factory.d.ts +1 -0
  171. package/dist/utils/llm-factory.d.ts.map +1 -1
  172. package/dist/utils/llm-factory.js +6 -1
  173. package/dist/utils/llm-factory.js.map +1 -1
  174. package/dist/utils/seed-context.d.ts +23 -0
  175. package/dist/utils/seed-context.d.ts.map +1 -0
  176. package/dist/utils/seed-context.js +38 -0
  177. package/dist/utils/seed-context.js.map +1 -0
  178. package/package.json +5 -5
  179. package/prompts/fk-pruning-holistic.md +7 -0
  180. package/prompts/fk-pruning-table.md +20 -1
  181. package/prompts/pk-pruning-holistic.md +7 -0
  182. package/prompts/pk-pruning-table.md +17 -0
  183. package/prompts/table-analysis.md +11 -0
@@ -0,0 +1,43 @@
1
+ /**
2
+ * A wall-clock ceiling on one model call.
3
+ *
4
+ * Every LLM call in this package was unbounded. That is not the same problem as "slow": the retry
5
+ * loops in `PromptEngine` only engage once a promise settles, and a provider that accepts the
6
+ * socket and then stops sending bytes never settles one — so a stall bypassed retry, backoff and
7
+ * error reporting alike and simply parked the run. `maxTokens` bounds the response, not the wait.
8
+ *
9
+ * Two mechanisms, deliberately both, mirroring how `AIPromptRunner.createExecutionBound` bounds its
10
+ * own calls:
11
+ *
12
+ * - the request is ABORTED via `ChatParams.cancellationToken`, which the provider drivers forward
13
+ * to their SDKs (`{ signal }` on the OpenAI client, and the equivalent on Gemini, LMStudio and
14
+ * BettyBot), so the connection is actually torn down;
15
+ * - the awaited promise is REJECTED, so a driver that ignores the signal — or a hang somewhere
16
+ * above the SDK — still cannot park the caller forever.
17
+ *
18
+ * Either alone is insufficient. Aborting without rejecting trusts every current and future driver
19
+ * to honour the signal. Rejecting without aborting leaves the request in flight, which is how a
20
+ * failing provider ends up holding ten open sockets while the caller opens an eleventh.
21
+ */
22
+ /** Default ceiling when `AIConfig.callTimeoutMs` is not set. */
23
+ export declare const DEFAULT_CALL_TIMEOUT_MS = 120000;
24
+ /** Resolves the configured ceiling. `0` (or a negative value) means no bound. */
25
+ export declare function ResolveCallTimeoutMs(configured: number | undefined): number;
26
+ /** Thrown when a model call exceeds its configured ceiling. */
27
+ export declare class LLMCallTimeoutError extends Error {
28
+ readonly TimeoutMs: number;
29
+ constructor(timeoutMs: number, what: string);
30
+ }
31
+ /**
32
+ * Runs `call` under a wall-clock ceiling.
33
+ *
34
+ * `call` receives the AbortSignal to attach to its `ChatParams.cancellationToken`. When
35
+ * `timeoutMs` is 0 the signal is `undefined` and the call runs exactly as it did before this
36
+ * existed, so disabling the bound restores the previous behaviour rather than approximating it.
37
+ *
38
+ * @param timeoutMs Resolved ceiling; 0 disables.
39
+ * @param what Description used in the timeout message (a prompt or table name).
40
+ * @param call Issues the request, attaching the supplied signal.
41
+ */
42
+ export declare function WithCallDeadline<T>(timeoutMs: number, what: string, call: (signal: AbortSignal | undefined) => Promise<T>): Promise<T>;
43
+ //# sourceMappingURL=call-deadline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-deadline.d.ts","sourceRoot":"","sources":["../../src/utils/call-deadline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,gEAAgE;AAChE,eAAO,MAAM,uBAAuB,SAAU,CAAC;AAE/C,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAK3E;AAED,+DAA+D;AAC/D,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAEtB,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAQ5C;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GACpD,OAAO,CAAC,CAAC,CAAC,CA4BZ"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * A wall-clock ceiling on one model call.
3
+ *
4
+ * Every LLM call in this package was unbounded. That is not the same problem as "slow": the retry
5
+ * loops in `PromptEngine` only engage once a promise settles, and a provider that accepts the
6
+ * socket and then stops sending bytes never settles one — so a stall bypassed retry, backoff and
7
+ * error reporting alike and simply parked the run. `maxTokens` bounds the response, not the wait.
8
+ *
9
+ * Two mechanisms, deliberately both, mirroring how `AIPromptRunner.createExecutionBound` bounds its
10
+ * own calls:
11
+ *
12
+ * - the request is ABORTED via `ChatParams.cancellationToken`, which the provider drivers forward
13
+ * to their SDKs (`{ signal }` on the OpenAI client, and the equivalent on Gemini, LMStudio and
14
+ * BettyBot), so the connection is actually torn down;
15
+ * - the awaited promise is REJECTED, so a driver that ignores the signal — or a hang somewhere
16
+ * above the SDK — still cannot park the caller forever.
17
+ *
18
+ * Either alone is insufficient. Aborting without rejecting trusts every current and future driver
19
+ * to honour the signal. Rejecting without aborting leaves the request in flight, which is how a
20
+ * failing provider ends up holding ten open sockets while the caller opens an eleventh.
21
+ */
22
+ /** Default ceiling when `AIConfig.callTimeoutMs` is not set. */
23
+ export const DEFAULT_CALL_TIMEOUT_MS = 120_000;
24
+ /** Resolves the configured ceiling. `0` (or a negative value) means no bound. */
25
+ export function ResolveCallTimeoutMs(configured) {
26
+ if (configured === undefined) {
27
+ return DEFAULT_CALL_TIMEOUT_MS;
28
+ }
29
+ return Number.isFinite(configured) && configured > 0 ? configured : 0;
30
+ }
31
+ /** Thrown when a model call exceeds its configured ceiling. */
32
+ export class LLMCallTimeoutError extends Error {
33
+ constructor(timeoutMs, what) {
34
+ // The word "timeout" is load-bearing: PromptEngine.isRetryableError and MJ's own ErrorAnalyzer
35
+ // both classify on message text, and a stall should be treated as retriable rather than fatal.
36
+ super(`${what} exceeded its ${timeoutMs}ms call timeout — the model call was aborted (timeout)`);
37
+ this.name = 'LLMCallTimeoutError';
38
+ this.TimeoutMs = timeoutMs;
39
+ Object.setPrototypeOf(this, LLMCallTimeoutError.prototype);
40
+ }
41
+ }
42
+ /**
43
+ * Runs `call` under a wall-clock ceiling.
44
+ *
45
+ * `call` receives the AbortSignal to attach to its `ChatParams.cancellationToken`. When
46
+ * `timeoutMs` is 0 the signal is `undefined` and the call runs exactly as it did before this
47
+ * existed, so disabling the bound restores the previous behaviour rather than approximating it.
48
+ *
49
+ * @param timeoutMs Resolved ceiling; 0 disables.
50
+ * @param what Description used in the timeout message (a prompt or table name).
51
+ * @param call Issues the request, attaching the supplied signal.
52
+ */
53
+ export async function WithCallDeadline(timeoutMs, what, call) {
54
+ if (timeoutMs <= 0) {
55
+ return call(undefined);
56
+ }
57
+ const controller = new AbortController();
58
+ let timer;
59
+ const expiry = new Promise((_resolve, reject) => {
60
+ timer = setTimeout(() => {
61
+ const err = new LLMCallTimeoutError(timeoutMs, what);
62
+ // Abort first so the in-flight request is cancelled, THEN reject. Rejecting first would let
63
+ // the caller move on — and start its next request — while this one is still open.
64
+ if (!controller.signal.aborted) {
65
+ controller.abort(err);
66
+ }
67
+ reject(err);
68
+ }, timeoutMs);
69
+ });
70
+ try {
71
+ return await Promise.race([call(controller.signal), expiry]);
72
+ }
73
+ finally {
74
+ // Always release the timer, on success, failure and timeout alike: a long-lived process would
75
+ // otherwise accumulate one per call.
76
+ if (timer) {
77
+ clearTimeout(timer);
78
+ }
79
+ }
80
+ }
81
+ //# sourceMappingURL=call-deadline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-deadline.js","sourceRoot":"","sources":["../../src/utils/call-deadline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,gEAAgE;AAChE,MAAM,CAAC,MAAM,uBAAuB,GAAG,OAAO,CAAC;AAE/C,iFAAiF;AACjF,MAAM,UAAU,oBAAoB,CAAC,UAA8B;IACjE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,uBAAuB,CAAC;IACjC,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,+DAA+D;AAC/D,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAG5C,YAAY,SAAiB,EAAE,IAAY;QACzC,+FAA+F;QAC/F,+FAA+F;QAC/F,KAAK,CAAC,GAAG,IAAI,iBAAiB,SAAS,wDAAwD,CAAC,CAAC;QACjG,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC7D,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,IAAY,EACZ,IAAqD;IAErD,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,KAAgD,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;QACrD,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,MAAM,GAAG,GAAG,IAAI,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YACrD,4FAA4F;YAC5F,kFAAkF;YAClF,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC/B,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxB,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,EAAE,SAAS,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,8FAA8F;QAC9F,qCAAqC;QACrC,IAAI,KAAK,EAAE,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -35,5 +35,10 @@ export declare class ConfigLoader {
35
35
  * Validate configuration
36
36
  */
37
37
  private static validate;
38
+ /**
39
+ * Resolve seedContext.file or seedContext.files if specified,
40
+ * reading contents and appending to customInstructions.
41
+ */
42
+ private static resolveSeedContextFiles;
38
43
  }
39
44
  //# sourceMappingURL=config-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,qBAAa,YAAY;IACvB;;;OAGG;WACiB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAqBtE,oCAAoC;WAChB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAItE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAU5B;;OAEG;WACiB,IAAI,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpF,oCAAoC;WAChB,IAAI,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpF;;OAEG;WACW,aAAa,IAAI,eAAe;IAuD9C,6CAA6C;WAC/B,aAAa,IAAI,eAAe;IAI9C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAkB5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ;CA6BxB"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,qBAAa,YAAY;IACvB;;;OAGG;WACiB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAwBtE,oCAAoC;WAChB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAItE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAU5B;;OAEG;WACiB,IAAI,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpF,oCAAoC;WAChB,IAAI,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpF;;OAEG;WACW,aAAa,IAAI,eAAe;IAuD9C,6CAA6C;WAC/B,aAAa,IAAI,eAAe;IAI9C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAkB5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ;IA+BvB;;;OAGG;mBACkB,uBAAuB;CA+B7C"}
@@ -14,6 +14,8 @@ export class ConfigLoader {
14
14
  // Expand environment variables in the content
15
15
  const expandedContent = this.expandEnvVars(content);
16
16
  const config = JSON.parse(expandedContent);
17
+ // Resolve seedContext.file or seedContext.files if specified
18
+ await this.resolveSeedContextFiles(config, path.dirname(configPath));
17
19
  // Validate required fields
18
20
  this.validate(config);
19
21
  // Apply defaults for optional sections
@@ -162,9 +164,44 @@ export class ConfigLoader {
162
164
  if (!config.ai.model) {
163
165
  throw new Error('Missing ai.model');
164
166
  }
167
+ config.ai.model = config.ai.model.trim();
165
168
  if (!config.ai.apiKey) {
166
169
  throw new Error('Missing ai.apiKey');
167
170
  }
168
171
  }
172
+ /**
173
+ * Resolve seedContext.file or seedContext.files if specified,
174
+ * reading contents and appending to customInstructions.
175
+ */
176
+ static async resolveSeedContextFiles(config, baseDir) {
177
+ if (!config.seedContext)
178
+ return;
179
+ const filesToLoad = [];
180
+ if (config.seedContext.file) {
181
+ filesToLoad.push(config.seedContext.file);
182
+ }
183
+ if (Array.isArray(config.seedContext.files)) {
184
+ filesToLoad.push(...config.seedContext.files);
185
+ }
186
+ if (filesToLoad.length === 0)
187
+ return;
188
+ const contents = [];
189
+ for (const relOrAbsPath of filesToLoad) {
190
+ const resolvedPath = path.isAbsolute(relOrAbsPath)
191
+ ? relOrAbsPath
192
+ : path.resolve(baseDir, relOrAbsPath);
193
+ try {
194
+ contents.push(await fs.readFile(resolvedPath, 'utf-8'));
195
+ }
196
+ catch (error) {
197
+ const setting = config.seedContext.file === relOrAbsPath ? 'seedContext.file' : 'seedContext.files';
198
+ throw new Error(`Could not read ${setting} entry '${relOrAbsPath}' (resolved to ${resolvedPath}): ${error.message}`);
199
+ }
200
+ }
201
+ const loadedText = contents.join('\n\n---\n\n');
202
+ config.seedContext.customInstructions = config.seedContext.customInstructions
203
+ ? `${config.seedContext.customInstructions}\n\n${loadedText}`
204
+ : loadedText;
205
+ }
169
206
  }
170
207
  //# sourceMappingURL=config-loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,OAAO,YAAY;IACvB;;;OAGG;IACI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAkB;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAEvD,8CAA8C;YAC9C,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAoB,CAAC;YAE9D,6DAA6D;YAC7D,MAAM,IAAI,CAAC,uBAAuB,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;YAErE,2BAA2B;YAC3B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAEtB,uCAAuC;YACvC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAE3B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,iCAAkC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,oCAAoC;IAC7B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAkB;QACzC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,aAAa,CAAC,OAAe;QAC1C,OAAO,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,iBAAiB,CAAC,CAAC;YACpE,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAuB,EAAE,UAAkB;QAClE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEzC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAChD,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,iCAAkC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,oCAAoC;IAC7B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAuB,EAAE,UAAkB;QAClE,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,aAAa;QACzB,OAAO;YACL,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE;gBACR,MAAM,EAAE,WAAW;gBACnB,IAAI,EAAE,IAAI;gBACV,QAAQ,EAAE,EAAE;gBACZ,IAAI,EAAE,EAAE;gBACR,QAAQ,EAAE,EAAE;gBACZ,OAAO,EAAE,IAAI;gBACb,sBAAsB,EAAE,KAAK;gBAC7B,iBAAiB,EAAE,KAAK;aACzB;YACD,EAAE,EAAE;gBACF,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,kBAAkB;gBACzB,MAAM,EAAE,EAAE;gBACV,WAAW,EAAE,GAAG;gBAChB,SAAS,EAAE,IAAI;aAChB;YACD,QAAQ,EAAE;gBACR,oBAAoB,EAAE,EAAE;gBACxB,UAAU,EAAE,EAAE;gBACd,iBAAiB,EAAE,IAAI;gBACvB,sBAAsB,EAAE,IAAI;gBAC5B,WAAW,EAAE;oBACX,aAAa,EAAE,CAAC;oBAChB,eAAe,EAAE,CAAC;oBAClB,mBAAmB,EAAE,IAAI;iBAC1B;gBACD,eAAe,EAAE;oBACf,OAAO,EAAE,IAAI;oBACb,QAAQ,EAAE,CAAC;iBACZ;gBACD,YAAY,EAAE;oBACZ,eAAe,EAAE,IAAI;oBACrB,WAAW,EAAE,IAAI;oBACjB,WAAW,EAAE,IAAI;iBAClB;aACF;YACD,MAAM,EAAE;gBACN,SAAS,EAAE,qBAAqB;gBAChC,OAAO,EAAE,+BAA+B;gBACxC,YAAY,EAAE,oCAAoC;aACnD;YACD,OAAO,EAAE;gBACP,OAAO,EAAE,EAAE;gBACX,OAAO,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC;aACvC;YACD,MAAM,EAAE;gBACN,OAAO,EAAE,CAAC,aAAa,EAAE,oBAAoB,CAAC;aAC/C;SACF,CAAC;IACJ,CAAC;IAED,6CAA6C;IACtC,MAAM,CAAC,aAAa;QACzB,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC;IAC9B,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,aAAa,CAAC,MAAuB;QAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,OAAO,GAAG,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,EAAE,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,CAAC,MAAM,GAAG,EAAE,OAAO,EAAE,CAAC,aAAa,EAAE,oBAAoB,CAAC,EAAE,CAAC;QACrE,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,CAAC,QAAQ,CAAC,WAAW,GAAG,EAAE,aAAa,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC;QACpG,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;YACrC,MAAM,CAAC,QAAQ,CAAC,eAAe,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACnE,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,CAAC,QAAQ,CAAC,YAAY,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QACjG,CAAC;IACH,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,QAAQ,CAAC,MAAuB;QAC7C,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,CAAC,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAEzC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,MAAuB,EAAE,OAAe;QACnF,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,OAAO;QAEhC,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAC5B,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAErC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,YAAY,IAAI,WAAW,EAAE,CAAC;YACvC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;gBAChD,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACxC,IAAI,CAAC;gBACH,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,mBAAmB,CAAC;gBACpG,MAAM,IAAI,KAAK,CAAC,kBAAkB,OAAO,WAAW,YAAY,kBAAkB,YAAY,MAAO,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YAClI,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAChD,MAAM,CAAC,WAAW,CAAC,kBAAkB,GAAG,MAAM,CAAC,WAAW,CAAC,kBAAkB;YAC3E,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,kBAAkB,OAAO,UAAU,EAAE;YAC7D,CAAC,CAAC,UAAU,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Existing indexes as evidence for the LLM passes.
3
+ *
4
+ * Databases "in the wild" often declare no primary or foreign keys but still have indexes on the
5
+ * columns people join and filter on. A unique index on non-null columns usually marks a primary or
6
+ * alternate key, and a non-unique index led by an ID-like column often marks a foreign key. These
7
+ * helpers turn the indexes stored on a table (`TableDefinition.indexes`) into prompt context.
8
+ */
9
+ import type { AutoDocIndex } from '../types/driver.js';
10
+ import type { SchemaDefinition, TableDefinition } from '../types/state.js';
11
+ /** One existing index, trimmed to what a prompt needs. */
12
+ export interface IndexHint {
13
+ Columns: string[];
14
+ IncludeColumns: string[];
15
+ IsUnique: boolean;
16
+ IsPrimaryKey: boolean;
17
+ /** Partial-index predicate, when the index covers only some rows. */
18
+ Filter?: string;
19
+ }
20
+ /** Most indexes a single table contributes to a prompt. */
21
+ export declare const MAX_INDEX_HINTS_PER_TABLE = 25;
22
+ /**
23
+ * The table's indexes as prompt hints, primary key first, then unique, then the rest, capped at
24
+ * `max`. Returns an empty array when the table has none or they were not loaded.
25
+ */
26
+ export declare function BuildIndexHints(table: Pick<TableDefinition, 'indexes'> | undefined, max?: number): IndexHint[];
27
+ /** One line per hint, e.g. `UNIQUE (Code) INCLUDE (Name) WHERE (Active = 1)`. */
28
+ export declare function FormatIndexHint(hint: IndexHint): string;
29
+ /**
30
+ * True when the column alone is the key of a primary-key or unique, unfiltered index on the table,
31
+ * i.e. the database already guarantees its values are distinct. Undefined when indexes were not loaded.
32
+ */
33
+ export declare function IsUniquelyIndexed(table: Pick<TableDefinition, 'indexes'> | undefined, column: string): boolean | undefined;
34
+ /** Attaches catalog indexes to the matching tables (exact name first, then case-insensitive). */
35
+ export declare function AttachIndexesToTables(tables: TableDefinition[], indexes: AutoDocIndex[]): void;
36
+ /**
37
+ * Decides which schemas still need their indexes read, honoring `analysis.useExistingIndexes`.
38
+ * When it is off, indexes left in a resumed state by an earlier run are dropped, so neither the prompt
39
+ * hints nor index-backed PK candidates use them, and nothing is returned to load. Otherwise returns the
40
+ * schemas with at least one table whose indexes were never read.
41
+ */
42
+ export declare function PrepareIndexesForRun(schemas: SchemaDefinition[], useExistingIndexes: boolean | undefined): SchemaDefinition[];
43
+ //# sourceMappingURL=index-hints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-hints.d.ts","sourceRoot":"","sources":["../../src/utils/index-hints.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE3E,0DAA0D;AAC1D,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,2DAA2D;AAC3D,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,SAAS,EAAE,GAAG,SAA4B,GAAG,SAAS,EAAE,CAYjI;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAKvD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAQ1H;AAED,iGAAiG;AACjG,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAc9F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,kBAAkB,EAAE,OAAO,GAAG,SAAS,GAAG,gBAAgB,EAAE,CAQ7H"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Existing indexes as evidence for the LLM passes.
3
+ *
4
+ * Databases "in the wild" often declare no primary or foreign keys but still have indexes on the
5
+ * columns people join and filter on. A unique index on non-null columns usually marks a primary or
6
+ * alternate key, and a non-unique index led by an ID-like column often marks a foreign key. These
7
+ * helpers turn the indexes stored on a table (`TableDefinition.indexes`) into prompt context.
8
+ */
9
+ /** Most indexes a single table contributes to a prompt. */
10
+ export const MAX_INDEX_HINTS_PER_TABLE = 25;
11
+ /**
12
+ * The table's indexes as prompt hints, primary key first, then unique, then the rest, capped at
13
+ * `max`. Returns an empty array when the table has none or they were not loaded.
14
+ */
15
+ export function BuildIndexHints(table, max = MAX_INDEX_HINTS_PER_TABLE) {
16
+ const indexes = table?.indexes ?? [];
17
+ return [...indexes]
18
+ .sort((a, b) => hintRank(a) - hintRank(b))
19
+ .slice(0, max)
20
+ .map((ix) => ({
21
+ Columns: ix.Columns,
22
+ IncludeColumns: ix.IncludeColumns,
23
+ IsUnique: ix.IsUnique || ix.IsPrimaryKey,
24
+ IsPrimaryKey: ix.IsPrimaryKey,
25
+ Filter: ix.FilterDefinition || undefined
26
+ }));
27
+ }
28
+ /** One line per hint, e.g. `UNIQUE (Code) INCLUDE (Name) WHERE (Active = 1)`. */
29
+ export function FormatIndexHint(hint) {
30
+ const kind = hint.IsPrimaryKey ? 'PRIMARY KEY' : hint.IsUnique ? 'UNIQUE' : 'INDEX';
31
+ const include = hint.IncludeColumns.length ? ` INCLUDE (${hint.IncludeColumns.join(', ')})` : '';
32
+ const filter = hint.Filter ? ` WHERE ${hint.Filter}` : '';
33
+ return `${kind} (${hint.Columns.join(', ')})${include}${filter}`;
34
+ }
35
+ /**
36
+ * True when the column alone is the key of a primary-key or unique, unfiltered index on the table,
37
+ * i.e. the database already guarantees its values are distinct. Undefined when indexes were not loaded.
38
+ */
39
+ export function IsUniquelyIndexed(table, column) {
40
+ if (!table?.indexes) {
41
+ return undefined;
42
+ }
43
+ const target = column.toLowerCase();
44
+ return table.indexes.some((ix) => (ix.IsUnique || ix.IsPrimaryKey) && !ix.FilterDefinition && ix.Columns.length === 1 && ix.Columns[0].toLowerCase() === target);
45
+ }
46
+ /** Attaches catalog indexes to the matching tables (exact name first, then case-insensitive). */
47
+ export function AttachIndexesToTables(tables, indexes) {
48
+ const exact = new Map();
49
+ for (const ix of indexes) {
50
+ const list = exact.get(ix.TableName) ?? [];
51
+ list.push(ix);
52
+ exact.set(ix.TableName, list);
53
+ }
54
+ const folded = new Map();
55
+ for (const [name, list] of exact) {
56
+ folded.set(name.toLowerCase(), [...(folded.get(name.toLowerCase()) ?? []), ...list]);
57
+ }
58
+ for (const table of tables) {
59
+ table.indexes = exact.get(table.name) ?? folded.get(table.name.toLowerCase()) ?? [];
60
+ }
61
+ }
62
+ /**
63
+ * Decides which schemas still need their indexes read, honoring `analysis.useExistingIndexes`.
64
+ * When it is off, indexes left in a resumed state by an earlier run are dropped, so neither the prompt
65
+ * hints nor index-backed PK candidates use them, and nothing is returned to load. Otherwise returns the
66
+ * schemas with at least one table whose indexes were never read.
67
+ */
68
+ export function PrepareIndexesForRun(schemas, useExistingIndexes) {
69
+ if (useExistingIndexes === false) {
70
+ for (const table of schemas.flatMap((s) => s.tables)) {
71
+ delete table.indexes;
72
+ }
73
+ return [];
74
+ }
75
+ return schemas.filter((s) => s.tables.some((t) => t.indexes === undefined));
76
+ }
77
+ function hintRank(ix) {
78
+ return ix.IsPrimaryKey ? 0 : ix.IsUnique ? 1 : 2;
79
+ }
80
+ //# sourceMappingURL=index-hints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-hints.js","sourceRoot":"","sources":["../../src/utils/index-hints.ts"],"names":[],"mappings":"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"}
@@ -2,4 +2,6 @@
2
2
  * Exports for utils module
3
3
  */
4
4
  export { ConfigLoader } from './config-loader.js';
5
+ export * from './index-hints.js';
6
+ export * from './seed-context.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
@@ -2,4 +2,6 @@
2
2
  * Exports for utils module
3
3
  */
4
4
  export { ConfigLoader } from './config-loader.js';
5
+ export * from './index-hints.js';
6
+ export * from './seed-context.js';
5
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
@@ -5,6 +5,7 @@
5
5
  * across PromptEngine and LLMSanityChecker.
6
6
  */
7
7
  import { BaseLLM } from '@memberjunction/ai';
8
+ import '@memberjunction/server-bootstrap-lite/mj-class-registrations';
8
9
  /**
9
10
  * Create an LLM instance from a provider name
10
11
  *
@@ -1 +1 @@
1
- {"version":3,"file":"llm-factory.d.ts","sourceRoot":"","sources":["../../src/utils/llm-factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAoB7C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAuB3E;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAE3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED,qDAAqD;AACrD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD"}
1
+ {"version":3,"file":"llm-factory.d.ts","sourceRoot":"","sources":["../../src/utils/llm-factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAI7C,OAAO,8DAA8D,CAAC;AAmBtE;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAyB3E;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAE3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED,qDAAqD;AACrD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD"}
@@ -6,6 +6,9 @@
6
6
  */
7
7
  import { BaseLLM } from '@memberjunction/ai';
8
8
  import { MJGlobal } from '@memberjunction/global';
9
+ // The LLM drivers register with MJGlobal.ClassFactory as a side effect of this manifest; without it a
10
+ // standalone CLI process has no provider classes to instantiate.
11
+ import '@memberjunction/server-bootstrap-lite/mj-class-registrations';
9
12
  /**
10
13
  * Provider name to LLM driver class name mapping
11
14
  */
@@ -37,7 +40,9 @@ export function CreateLLMInstance(provider, apiKey) {
37
40
  throw new Error(`Unknown provider: ${provider}. Supported providers: ${supportedProviders}`);
38
41
  }
39
42
  const llm = MJGlobal.Instance.ClassFactory.CreateInstance(BaseLLM, driverClass, apiKey);
40
- if (!llm) {
43
+ // The ClassFactory falls back to the base class when nothing is registered under the key, and a bare
44
+ // BaseLLM fails on every call, so treat that as "not installed" too.
45
+ if (!llm || Object.getPrototypeOf(llm) === BaseLLM.prototype) {
41
46
  throw new Error(`Failed to create LLM instance for provider: ${provider} (driver class: ${driverClass}). Check that the provider is installed.`);
42
47
  }
43
48
  return llm;
@@ -1 +1 @@
1
- {"version":3,"file":"llm-factory.js","sourceRoot":"","sources":["../../src/utils/llm-factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD;;GAEG;AACH,MAAM,wBAAwB,GAA2B;IACvD,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,WAAW;IACrB,WAAW,EAAE,cAAc;IAC3B,MAAM,EAAE,SAAS;IACjB,SAAS,EAAE,YAAY;IACvB,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,UAAU;IACnB,UAAU,EAAE,aAAa;IACzB,YAAY,EAAE,eAAe;IAC7B,KAAK,EAAE,QAAQ;IACf,SAAS,EAAE,YAAY;CACxB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,MAAc;IAChE,MAAM,WAAW,GAAG,wBAAwB,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAErE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,MAAM,IAAI,KAAK,CACb,qBAAqB,QAAQ,0BAA0B,kBAAkB,EAAE,CAC5E,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc,CACvD,OAAO,EACP,WAAW,EACX,MAAM,CACP,CAAC;IAEF,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,+CAA+C,QAAQ,mBAAmB,WAAW,0CAA0C,CAChI,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,MAAc;IAChE,OAAO,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,wBAAwB,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AAC/C,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,qBAAqB;IACnC,OAAO,qBAAqB,EAAE,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"llm-factory.js","sourceRoot":"","sources":["../../src/utils/llm-factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,sGAAsG;AACtG,iEAAiE;AACjE,OAAO,8DAA8D,CAAC;AAEtE;;GAEG;AACH,MAAM,wBAAwB,GAA2B;IACvD,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,WAAW;IACrB,WAAW,EAAE,cAAc;IAC3B,MAAM,EAAE,SAAS;IACjB,SAAS,EAAE,YAAY;IACvB,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,UAAU;IACnB,UAAU,EAAE,aAAa;IACzB,YAAY,EAAE,eAAe;IAC7B,KAAK,EAAE,QAAQ;IACf,SAAS,EAAE,YAAY;CACxB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,MAAc;IAChE,MAAM,WAAW,GAAG,wBAAwB,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAErE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,MAAM,IAAI,KAAK,CACb,qBAAqB,QAAQ,0BAA0B,kBAAkB,EAAE,CAC5E,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc,CACvD,OAAO,EACP,WAAW,EACX,MAAM,CACP,CAAC;IAEF,qGAAqG;IACrG,qEAAqE;IACrE,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,+CAA+C,QAAQ,mBAAmB,WAAW,0CAA0C,CAChI,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,MAAc;IAChE,OAAO,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,wBAAwB,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AAC/C,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,qBAAqB;IACnC,OAAO,qBAAqB,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The part of the operator's seed context (`seedContext.customInstructions`, which also holds the
3
+ * text of `seedContext.file` / `files`) that is worth sending to a key-inference prompt.
4
+ *
5
+ * The table-analysis prompt gets the whole text. The PK/FK passes run once per table, so sending a
6
+ * long data-layout document to each of them would multiply its cost by the table count. A
7
+ * per-table pass gets only the paragraphs that name its table; a whole-schema pass gets the text.
8
+ * Both are capped.
9
+ */
10
+ /** Default cap on the seed text sent to one key-inference prompt, in characters. */
11
+ export declare const DEFAULT_SEED_KEY_PASS_MAX_CHARS = 6000;
12
+ /** The fields of a seed context this module reads; satisfied by both the config and state shapes. */
13
+ export interface SeedContextText {
14
+ customInstructions?: string;
15
+ keyPassMaxChars?: number;
16
+ }
17
+ /**
18
+ * Returns the seed text for a key-inference prompt, or undefined when there is none to send.
19
+ * @param seed the seed context from config or state
20
+ * @param tableNames the tables the prompt is about; empty for a whole-schema prompt
21
+ */
22
+ export declare function SeedContextExcerpt(seed: SeedContextText | undefined, tableNames: string[]): string | undefined;
23
+ //# sourceMappingURL=seed-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed-context.d.ts","sourceRoot":"","sources":["../../src/utils/seed-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,oFAAoF;AACpF,eAAO,MAAM,+BAA+B,OAAO,CAAC;AAEpD,qGAAqG;AACrG,MAAM,WAAW,eAAe;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAmB9G"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The part of the operator's seed context (`seedContext.customInstructions`, which also holds the
3
+ * text of `seedContext.file` / `files`) that is worth sending to a key-inference prompt.
4
+ *
5
+ * The table-analysis prompt gets the whole text. The PK/FK passes run once per table, so sending a
6
+ * long data-layout document to each of them would multiply its cost by the table count. A
7
+ * per-table pass gets only the paragraphs that name its table; a whole-schema pass gets the text.
8
+ * Both are capped.
9
+ */
10
+ /** Default cap on the seed text sent to one key-inference prompt, in characters. */
11
+ export const DEFAULT_SEED_KEY_PASS_MAX_CHARS = 6000;
12
+ /**
13
+ * Returns the seed text for a key-inference prompt, or undefined when there is none to send.
14
+ * @param seed the seed context from config or state
15
+ * @param tableNames the tables the prompt is about; empty for a whole-schema prompt
16
+ */
17
+ export function SeedContextExcerpt(seed, tableNames) {
18
+ const text = seed?.customInstructions?.trim();
19
+ const maxChars = seed?.keyPassMaxChars ?? DEFAULT_SEED_KEY_PASS_MAX_CHARS;
20
+ if (!text || maxChars <= 0) {
21
+ return undefined;
22
+ }
23
+ let excerpt = text;
24
+ if (tableNames.length > 0) {
25
+ const matchers = tableNames.map(name => new RegExp(`(^|[^A-Za-z0-9_])${escapeRegExp(name)}([^A-Za-z0-9_]|$)`, 'i'));
26
+ const paragraphs = text.split(/\n\s*\n/).map(p => p.trim()).filter(p => p.length > 0);
27
+ const relevant = paragraphs.filter(p => matchers.some(m => m.test(p)));
28
+ if (relevant.length === 0) {
29
+ return undefined;
30
+ }
31
+ excerpt = relevant.join('\n\n');
32
+ }
33
+ return excerpt.length > maxChars ? `${excerpt.slice(0, maxChars)}\n…(truncated)` : excerpt;
34
+ }
35
+ function escapeRegExp(text) {
36
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
37
+ }
38
+ //# sourceMappingURL=seed-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed-context.js","sourceRoot":"","sources":["../../src/utils/seed-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,oFAAoF;AACpF,MAAM,CAAC,MAAM,+BAA+B,GAAG,IAAI,CAAC;AAQpD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAiC,EAAE,UAAoB;IACxF,MAAM,IAAI,GAAG,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,EAAE,eAAe,IAAI,+BAA+B,CAAC;IAC1E,IAAI,CAAC,IAAI,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,oBAAoB,YAAY,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC,CAAC;QACpH,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACtF,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC;AAC7F,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/db-auto-doc",
3
3
  "type": "module",
4
- "version": "6.2.0-edge.4",
4
+ "version": "6.2.0-edge.6",
5
5
  "description": "AI-powered database documentation generator for SQL Server, MySQL, and PostgreSQL. Analyzes your database structure, uses AI to generate comprehensive descriptions, and saves them as metadata. Works standalone - no MemberJunction runtime required.",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -64,10 +64,10 @@
64
64
  },
65
65
  "dependencies": {
66
66
  "@inquirer/prompts": "^8.2.0",
67
- "@memberjunction/ai": "6.2.0-edge.4",
68
- "@memberjunction/server-bootstrap-lite": "6.2.0-edge.4",
69
- "@memberjunction/core": "6.2.0-edge.4",
70
- "@memberjunction/global": "6.2.0-edge.4",
67
+ "@memberjunction/ai": "6.2.0-edge.6",
68
+ "@memberjunction/server-bootstrap-lite": "6.2.0-edge.6",
69
+ "@memberjunction/core": "6.2.0-edge.6",
70
+ "@memberjunction/global": "6.2.0-edge.6",
71
71
  "@oclif/core": "^3.27.0",
72
72
  "@oclif/plugin-help": "^6.2.37",
73
73
  "chalk": "^5.6.2",
@@ -20,6 +20,13 @@ The per-table analysis proposed removing these FKs. Review each one and decide w
20
20
  - **Removal reason**: {{ proposal.reasoning }}
21
21
  {% endfor %}
22
22
 
23
+ {% if seedExcerpt %}
24
+ ## Notes from the operator about this data
25
+ Written by the person running the analysis. Treat them as evidence about how tables relate and which columns are keys; they do not override what the data and constraints show.
26
+
27
+ {{ seedExcerpt }}
28
+
29
+ {% endif %}
23
30
  ## Review Guidelines
24
31
 
25
32
  Consider the FULL relationship graph when making decisions:
@@ -14,9 +14,28 @@ These FKs were identified by statistical analysis and/or LLM analysis. Some are
14
14
  **NOTE**: FKs marked as **[LOCKED]** have very high confidence and CANNOT be removed. Only evaluate the unlocked ones.
15
15
 
16
16
  {% for fk in candidates %}
17
- {{ loop.index }}. {% if fk.locked %}**[LOCKED]** {% endif %}**{{ fk.sourceColumn }}** → {{ fk.targetSchema }}.{{ fk.targetTable }}.{{ fk.targetColumn }} (confidence: {{ fk.confidence }}%)
17
+ {{ loop.index }}. {% if fk.locked %}**[LOCKED]** {% endif %}**{{ fk.sourceColumn }}** → {{ fk.targetSchema }}.{{ fk.targetTable }}.{{ fk.targetColumn }} (confidence: {{ fk.confidence }}%{% if fk.targetUniquelyIndexed === true %}; target column has a unique index{% elif fk.targetUniquelyIndexed === false %}; target column has no unique index{% endif %})
18
18
  {% endfor %}
19
19
 
20
+ {% if existingIndexes and existingIndexes.length > 0 %}
21
+ ## Existing Indexes
22
+ These indexes exist on this table in the database. Developers index the columns they join and filter on, so indexes are clues to keys even when none are declared:
23
+ {% for ix in existingIndexes %}
24
+ - {{ ix }}
25
+ {% endfor %}
26
+
27
+ *A UNIQUE index or PRIMARY KEY on non-null columns is strong evidence of the primary key (or an alternate key). A non-unique index led by an ID- or code-like column often marks a foreign key. Indexes are evidence, not proof — weigh them with names, statistics and value overlap. "(expression)" is a computed key part.*
28
+ {% endif %}
29
+
30
+ *A real FK target is normally unique. A target column with a unique index or primary key supports the FK; one without is weaker evidence (but the database may simply not declare it).*
31
+
32
+ {% if seedExcerpt %}
33
+ ## Notes from the operator about this data
34
+ Written by the person running the analysis. Treat them as evidence about how tables relate and which columns are keys; they do not override what the data and constraints show.
35
+
36
+ {{ seedExcerpt }}
37
+
38
+ {% endif %}
20
39
  ## What to look for when proposing removals:
21
40
 
22
41
  1. **Reverse direction**: FK goes from parent→child instead of child→parent. Example: `Department.DepartmentID → EmployeeDepartmentHistory.DepartmentID` is backwards — the history table should reference Department, not the other way around.
@@ -11,6 +11,13 @@ You are performing a final review of proposed primary key removals across a data
11
11
  - {{ tbl.schema }}.{{ tbl.name }}{% if tbl.pk %} (PK: {{ tbl.pk }}){% endif %}{% if tbl.description %} — {{ tbl.description }}{% endif %}
12
12
  {% endfor %}
13
13
 
14
+ {% if seedExcerpt %}
15
+ ## Notes from the operator about this data
16
+ Written by the person running the analysis. Treat them as evidence about how tables relate and which columns are keys; they do not override what the data and constraints show.
17
+
18
+ {{ seedExcerpt }}
19
+
20
+ {% endif %}
14
21
  ## Your Task:
15
22
  Review each proposed removal. Consider:
16
23
  1. Would removing this PK leave the table without any primary key?