@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.
- package/README.md +105 -0
- package/dist/api/DBAutoDocAPI.d.ts +2 -0
- package/dist/api/DBAutoDocAPI.d.ts.map +1 -1
- package/dist/api/DBAutoDocAPI.js +2 -1
- package/dist/api/DBAutoDocAPI.js.map +1 -1
- package/dist/commands/analyze.d.ts +1 -0
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +6 -0
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/export.d.ts +28 -19
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +91 -12
- package/dist/commands/export.js.map +1 -1
- package/dist/core/AnalysisEngine.d.ts +39 -6
- package/dist/core/AnalysisEngine.d.ts.map +1 -1
- package/dist/core/AnalysisEngine.js +144 -50
- package/dist/core/AnalysisEngine.js.map +1 -1
- package/dist/core/AnalysisOrchestrator.d.ts +20 -1
- package/dist/core/AnalysisOrchestrator.d.ts.map +1 -1
- package/dist/core/AnalysisOrchestrator.js +144 -28
- package/dist/core/AnalysisOrchestrator.js.map +1 -1
- package/dist/core/PKProposalGate.d.ts +22 -0
- package/dist/core/PKProposalGate.d.ts.map +1 -0
- package/dist/core/PKProposalGate.js +52 -0
- package/dist/core/PKProposalGate.js.map +1 -0
- package/dist/database/Database.d.ts +8 -0
- package/dist/database/Database.d.ts.map +1 -1
- package/dist/database/Database.js +23 -1
- package/dist/database/Database.js.map +1 -1
- package/dist/discovery/ColumnNormalizer.d.ts +31 -0
- package/dist/discovery/ColumnNormalizer.d.ts.map +1 -1
- package/dist/discovery/ColumnNormalizer.js +68 -2
- package/dist/discovery/ColumnNormalizer.js.map +1 -1
- package/dist/discovery/Composer.d.ts +33 -2
- package/dist/discovery/Composer.d.ts.map +1 -1
- package/dist/discovery/Composer.js +126 -5
- package/dist/discovery/Composer.js.map +1 -1
- package/dist/discovery/DiscoveryEngine.d.ts +3 -0
- package/dist/discovery/DiscoveryEngine.d.ts.map +1 -1
- package/dist/discovery/DiscoveryEngine.js +1 -1
- package/dist/discovery/DiscoveryEngine.js.map +1 -1
- package/dist/discovery/EmbeddingProvider.d.ts +6 -1
- package/dist/discovery/EmbeddingProvider.d.ts.map +1 -1
- package/dist/discovery/EmbeddingProvider.js +11 -1
- package/dist/discovery/EmbeddingProvider.js.map +1 -1
- package/dist/discovery/EnumCandidateGate.d.ts +19 -0
- package/dist/discovery/EnumCandidateGate.d.ts.map +1 -1
- package/dist/discovery/EnumCandidateGate.js +47 -5
- package/dist/discovery/EnumCandidateGate.js.map +1 -1
- package/dist/discovery/FKGraphWalker.d.ts +35 -0
- package/dist/discovery/FKGraphWalker.d.ts.map +1 -1
- package/dist/discovery/FKGraphWalker.js +113 -12
- package/dist/discovery/FKGraphWalker.js.map +1 -1
- package/dist/discovery/IndexKeyEvidence.d.ts +36 -0
- package/dist/discovery/IndexKeyEvidence.d.ts.map +1 -0
- package/dist/discovery/IndexKeyEvidence.js +42 -0
- package/dist/discovery/IndexKeyEvidence.js.map +1 -0
- package/dist/discovery/JoinProbe.d.ts +148 -0
- package/dist/discovery/JoinProbe.d.ts.map +1 -0
- package/dist/discovery/JoinProbe.js +233 -0
- package/dist/discovery/JoinProbe.js.map +1 -0
- package/dist/discovery/LLMDiscoveryValidator.d.ts +10 -1
- package/dist/discovery/LLMDiscoveryValidator.d.ts.map +1 -1
- package/dist/discovery/LLMDiscoveryValidator.js +44 -12
- package/dist/discovery/LLMDiscoveryValidator.js.map +1 -1
- package/dist/discovery/LLMSanityChecker.d.ts.map +1 -1
- package/dist/discovery/LLMSanityChecker.js +10 -1
- package/dist/discovery/LLMSanityChecker.js.map +1 -1
- package/dist/discovery/OrganicKeyDetector.d.ts +29 -1
- package/dist/discovery/OrganicKeyDetector.d.ts.map +1 -1
- package/dist/discovery/OrganicKeyDetector.js +34 -5
- package/dist/discovery/OrganicKeyDetector.js.map +1 -1
- package/dist/discovery/OrganicKeyTranslator.d.ts +24 -5
- package/dist/discovery/OrganicKeyTranslator.d.ts.map +1 -1
- package/dist/discovery/OrganicKeyTranslator.js +32 -14
- package/dist/discovery/OrganicKeyTranslator.js.map +1 -1
- package/dist/discovery/PKDetector.d.ts +9 -0
- package/dist/discovery/PKDetector.d.ts.map +1 -1
- package/dist/discovery/PKDetector.js +86 -8
- package/dist/discovery/PKDetector.js.map +1 -1
- package/dist/discovery/SemanticPhase.d.ts +25 -0
- package/dist/discovery/SemanticPhase.d.ts.map +1 -1
- package/dist/discovery/SemanticPhase.js +55 -11
- package/dist/discovery/SemanticPhase.js.map +1 -1
- package/dist/discovery/StructuralPhase.d.ts +27 -5
- package/dist/discovery/StructuralPhase.d.ts.map +1 -1
- package/dist/discovery/StructuralPhase.js +42 -9
- package/dist/discovery/StructuralPhase.js.map +1 -1
- package/dist/discovery/TransitiveBridgeDetector.d.ts +5 -1
- package/dist/discovery/TransitiveBridgeDetector.d.ts.map +1 -1
- package/dist/discovery/TransitiveBridgeDetector.js +25 -3
- package/dist/discovery/TransitiveBridgeDetector.js.map +1 -1
- package/dist/discovery/embedding-provider-default.d.ts +25 -0
- package/dist/discovery/embedding-provider-default.d.ts.map +1 -0
- package/dist/discovery/embedding-provider-default.js +47 -0
- package/dist/discovery/embedding-provider-default.js.map +1 -0
- package/dist/drivers/BaseAutoDocDriver.d.ts +63 -0
- package/dist/drivers/BaseAutoDocDriver.d.ts.map +1 -1
- package/dist/drivers/BaseAutoDocDriver.js +3 -5
- package/dist/drivers/BaseAutoDocDriver.js.map +1 -1
- package/dist/drivers/MySQLDriver.d.ts +21 -1
- package/dist/drivers/MySQLDriver.d.ts.map +1 -1
- package/dist/drivers/MySQLDriver.js +64 -0
- package/dist/drivers/MySQLDriver.js.map +1 -1
- package/dist/drivers/PostgreSQLDriver.d.ts +43 -2
- package/dist/drivers/PostgreSQLDriver.d.ts.map +1 -1
- package/dist/drivers/PostgreSQLDriver.js +132 -19
- package/dist/drivers/PostgreSQLDriver.js.map +1 -1
- package/dist/drivers/SQLServerDriver.d.ts +28 -1
- package/dist/drivers/SQLServerDriver.d.ts.map +1 -1
- package/dist/drivers/SQLServerDriver.js +108 -1
- package/dist/drivers/SQLServerDriver.js.map +1 -1
- package/dist/drivers/probeErrors.d.ts +30 -0
- package/dist/drivers/probeErrors.d.ts.map +1 -0
- package/dist/drivers/probeErrors.js +94 -0
- package/dist/drivers/probeErrors.js.map +1 -0
- package/dist/generators/AdditionalSchemaInfoGenerator.d.ts +34 -18
- package/dist/generators/AdditionalSchemaInfoGenerator.d.ts.map +1 -1
- package/dist/generators/AdditionalSchemaInfoGenerator.js +130 -8
- package/dist/generators/AdditionalSchemaInfoGenerator.js.map +1 -1
- package/dist/generators/ErdClusterGenerator.d.ts +44 -0
- package/dist/generators/ErdClusterGenerator.d.ts.map +1 -0
- package/dist/generators/ErdClusterGenerator.js +216 -0
- package/dist/generators/ErdClusterGenerator.js.map +1 -0
- package/dist/generators/ErdClusterer.d.ts +130 -0
- package/dist/generators/ErdClusterer.d.ts.map +1 -0
- package/dist/generators/ErdClusterer.js +308 -0
- package/dist/generators/ErdClusterer.js.map +1 -0
- package/dist/generators/HTMLGenerator.d.ts +6 -0
- package/dist/generators/HTMLGenerator.d.ts.map +1 -1
- package/dist/generators/HTMLGenerator.js +41 -6
- package/dist/generators/HTMLGenerator.js.map +1 -1
- package/dist/generators/MermaidGenerator.d.ts +3 -0
- package/dist/generators/MermaidGenerator.d.ts.map +1 -1
- package/dist/generators/MermaidGenerator.js +4 -0
- package/dist/generators/MermaidGenerator.js.map +1 -1
- package/dist/generators/index.d.ts +2 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +2 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/prompts/PromptEngine.d.ts.map +1 -1
- package/dist/prompts/PromptEngine.js +10 -1
- package/dist/prompts/PromptEngine.js.map +1 -1
- package/dist/types/analysis.d.ts +2 -0
- package/dist/types/analysis.d.ts.map +1 -1
- package/dist/types/config.d.ts +128 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +7 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/discovery.d.ts +41 -0
- package/dist/types/discovery.d.ts.map +1 -1
- package/dist/types/state.d.ts +29 -0
- package/dist/types/state.d.ts.map +1 -1
- package/dist/utils/call-deadline.d.ts +43 -0
- package/dist/utils/call-deadline.d.ts.map +1 -0
- package/dist/utils/call-deadline.js +81 -0
- package/dist/utils/call-deadline.js.map +1 -0
- package/dist/utils/config-loader.d.ts +5 -0
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +37 -0
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/index-hints.d.ts +43 -0
- package/dist/utils/index-hints.d.ts.map +1 -0
- package/dist/utils/index-hints.js +80 -0
- package/dist/utils/index-hints.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/llm-factory.d.ts +1 -0
- package/dist/utils/llm-factory.d.ts.map +1 -1
- package/dist/utils/llm-factory.js +6 -1
- package/dist/utils/llm-factory.js.map +1 -1
- package/dist/utils/seed-context.d.ts +23 -0
- package/dist/utils/seed-context.d.ts.map +1 -0
- package/dist/utils/seed-context.js +38 -0
- package/dist/utils/seed-context.js.map +1 -0
- package/package.json +5 -5
- package/prompts/fk-pruning-holistic.md +7 -0
- package/prompts/fk-pruning-table.md +20 -1
- package/prompts/pk-pruning-holistic.md +7 -0
- package/prompts/pk-pruning-table.md +17 -0
- 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;
|
|
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":"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"}
|
|
@@ -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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"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -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"}
|
package/dist/utils/index.js
CHANGED
package/dist/utils/index.js.map
CHANGED
|
@@ -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"}
|
|
@@ -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;
|
|
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
|
-
|
|
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;
|
|
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
|
+
"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.
|
|
68
|
-
"@memberjunction/server-bootstrap-lite": "6.2.0-edge.
|
|
69
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
70
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
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?
|