sela-core 0.1.0-alpha.39 → 0.1.0-alpha.41
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/dist/boot/bootImpl.d.ts +14 -0
- package/dist/boot/bootImpl.d.ts.map +1 -0
- package/dist/boot/bootImpl.js +68 -0
- package/dist/boot/register.cjs +45 -0
- package/dist/boot/register.d.cts +2 -0
- package/dist/boot/register.d.cts.map +1 -0
- package/dist/boot/register.d.mts +2 -0
- package/dist/boot/register.d.mts.map +1 -0
- package/dist/boot/register.mjs +10 -0
- package/dist/cli/commands/init.js +48 -16
- package/dist/cli/commands/merge.d.ts.map +1 -1
- package/dist/cli/commands/merge.js +5 -0
- package/dist/cli/commands/shadowRegression.js +1 -1
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +33 -12
- package/dist/config/SelaConfig.d.ts +59 -0
- package/dist/config/SelaConfig.d.ts.map +1 -1
- package/dist/config/SelaConfig.js +36 -0
- package/dist/engine/SelaEngine.d.ts +3 -1
- package/dist/engine/SelaEngine.d.ts.map +1 -1
- package/dist/engine/SelaEngine.js +193 -3
- package/dist/errors/SelaError.d.ts +7 -0
- package/dist/errors/SelaError.d.ts.map +1 -1
- package/dist/errors/SelaError.js +7 -1
- package/dist/fixtures/index.d.ts.map +1 -1
- package/dist/fixtures/index.js +5 -4
- package/dist/providers/AnthropicProvider.d.ts +9 -0
- package/dist/providers/AnthropicProvider.d.ts.map +1 -0
- package/dist/providers/AnthropicProvider.js +33 -0
- package/dist/providers/LLMProvider.d.ts +13 -0
- package/dist/providers/LLMProvider.d.ts.map +1 -0
- package/dist/providers/LLMProvider.js +7 -0
- package/dist/providers/OpenAICompatibleProvider.d.ts +8 -0
- package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -0
- package/dist/providers/OpenAICompatibleProvider.js +48 -0
- package/dist/providers/ProviderFactory.d.ts +4 -0
- package/dist/providers/ProviderFactory.d.ts.map +1 -0
- package/dist/providers/ProviderFactory.js +50 -0
- package/dist/providers/SanitizingProvider.d.ts +8 -0
- package/dist/providers/SanitizingProvider.d.ts.map +1 -0
- package/dist/providers/SanitizingProvider.js +27 -0
- package/dist/services/ASTSourceUpdater.d.ts.map +1 -1
- package/dist/services/ASTSourceUpdater.js +39 -5
- package/dist/services/CrossFileHealer.d.ts +7 -1
- package/dist/services/CrossFileHealer.d.ts.map +1 -1
- package/dist/services/CrossFileHealer.js +243 -9
- package/dist/services/DefinitionTracer.d.ts +1 -0
- package/dist/services/DefinitionTracer.d.ts.map +1 -1
- package/dist/services/DefinitionTracer.js +59 -36
- package/dist/services/HealReportService.d.ts +32 -0
- package/dist/services/HealReportService.d.ts.map +1 -1
- package/dist/services/HealReportService.js +111 -18
- package/dist/services/IntentAuditor.d.ts +9 -7
- package/dist/services/IntentAuditor.d.ts.map +1 -1
- package/dist/services/IntentAuditor.js +21 -16
- package/dist/services/LLMService.d.ts +10 -7
- package/dist/services/LLMService.d.ts.map +1 -1
- package/dist/services/LLMService.js +76 -10
- package/dist/services/PRAutomationService.d.ts +7 -2
- package/dist/services/PRAutomationService.d.ts.map +1 -1
- package/dist/services/PRAutomationService.js +144 -133
- package/dist/services/RegressionManifestService.d.ts +8 -0
- package/dist/services/RegressionManifestService.d.ts.map +1 -1
- package/dist/services/RegressionManifestService.js +8 -0
- package/dist/services/RegressionReclassifier.d.ts +25 -0
- package/dist/services/RegressionReclassifier.d.ts.map +1 -0
- package/dist/services/RegressionReclassifier.js +195 -0
- package/dist/services/ReportMergeService.d.ts +9 -0
- package/dist/services/ReportMergeService.d.ts.map +1 -1
- package/dist/services/ReportMergeService.js +28 -0
- package/dist/services/SmartDOMPruner.d.ts +154 -0
- package/dist/services/SmartDOMPruner.d.ts.map +1 -0
- package/dist/services/SmartDOMPruner.js +678 -0
- package/dist/services/TraceBackEngine.d.ts +23 -6
- package/dist/services/TraceBackEngine.d.ts.map +1 -1
- package/dist/services/TraceBackEngine.js +51 -13
- package/dist/services/VisualSnapshotService.d.ts +54 -0
- package/dist/services/VisualSnapshotService.d.ts.map +1 -0
- package/dist/services/VisualSnapshotService.js +279 -0
- package/dist/services/vcs/GitHubProvider.d.ts +17 -0
- package/dist/services/vcs/GitHubProvider.d.ts.map +1 -0
- package/dist/services/vcs/GitHubProvider.js +162 -0
- package/dist/services/vcs/GitLabProvider.d.ts +17 -0
- package/dist/services/vcs/GitLabProvider.d.ts.map +1 -0
- package/dist/services/vcs/GitLabProvider.js +175 -0
- package/dist/services/vcs/VCSProvider.d.ts +100 -0
- package/dist/services/vcs/VCSProvider.d.ts.map +1 -0
- package/dist/services/vcs/VCSProvider.js +7 -0
- package/dist/services/vcs/VCSProviderFactory.d.ts +7 -0
- package/dist/services/vcs/VCSProviderFactory.d.ts.map +1 -0
- package/dist/services/vcs/VCSProviderFactory.js +42 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/shell.d.ts +7 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +32 -0
- package/package.json +7 -1
|
@@ -47,6 +47,8 @@ const ASTSourceUpdater_1 = require("../services/ASTSourceUpdater");
|
|
|
47
47
|
const SafetyGuard_1 = require("../services/SafetyGuard");
|
|
48
48
|
const HealingCacheService_1 = require("../services/HealingCacheService");
|
|
49
49
|
const ConfigLoader_1 = require("../config/ConfigLoader");
|
|
50
|
+
const ProviderFactory_1 = require("../providers/ProviderFactory");
|
|
51
|
+
const IntentAuditor_1 = require("../services/IntentAuditor");
|
|
50
52
|
const DryRunGuard_1 = require("../config/DryRunGuard");
|
|
51
53
|
const HealBudget_1 = require("../services/HealBudget");
|
|
52
54
|
const HealReportService_1 = require("../services/HealReportService");
|
|
@@ -58,6 +60,7 @@ const SelaError_1 = require("../errors/SelaError");
|
|
|
58
60
|
const SelaHealingRefusalError_1 = require("../errors/SelaHealingRefusalError");
|
|
59
61
|
const FileWriteInterceptor_1 = require("../services/interceptors/FileWriteInterceptor");
|
|
60
62
|
const SelectorSanitizer_1 = require("../services/SelectorSanitizer");
|
|
63
|
+
const VisualSnapshotService_1 = require("../services/VisualSnapshotService");
|
|
61
64
|
/**
|
|
62
65
|
* Graceful percentage formatter for engine-side log lines. Mirrors the helper
|
|
63
66
|
* in PRAutomationService / HealReportService so a missing AI/auditor
|
|
@@ -113,13 +116,24 @@ class SelaEngine {
|
|
|
113
116
|
// immediate in-memory hit without a second LLM round-trip or any page.evaluate
|
|
114
117
|
// call (which would fail when the page is already closed, e.g. unawaited promises).
|
|
115
118
|
bypassedSelectorCache = new Map();
|
|
119
|
+
// NO_HEAL cache: elementSelectorOnly → reason. Once a selector is identified
|
|
120
|
+
// as an application logic/state failure (not selector drift) in this run,
|
|
121
|
+
// all subsequent heal() calls for the same selector skip LLM entirely.
|
|
122
|
+
noHealCache = new Map();
|
|
116
123
|
constructor() {
|
|
117
124
|
this.config = ConfigLoader_1.ConfigLoader.getInstance();
|
|
118
125
|
// Seed the per-run heal budget (T2). null => unlimited.
|
|
119
126
|
HealBudget_1.sharedHealBudget.configure(this.config.maxHealsPerRun);
|
|
120
|
-
|
|
127
|
+
// Build provider-abstracted LLM clients from resolved config.
|
|
128
|
+
// Each model can point to a different provider / endpoint.
|
|
129
|
+
const healingProvider = (0, ProviderFactory_1.createProvider)(this.config.llm.healingModel, this.config.sanitization);
|
|
130
|
+
const auditProvider = (0, ProviderFactory_1.createProvider)(this.config.llm.intentAuditModel, this.config.sanitization);
|
|
131
|
+
this.llmService = new LLMService_1.LLMService({ provider: healingProvider });
|
|
121
132
|
this.snapshotService = new SnapshotService_1.SnapshotService();
|
|
122
|
-
this.safetyGuard = new SafetyGuard_1.SafetyGuard(
|
|
133
|
+
this.safetyGuard = new SafetyGuard_1.SafetyGuard({
|
|
134
|
+
thresholds: this.config.thresholds,
|
|
135
|
+
intentAuditor: new IntentAuditor_1.IntentAuditor({ provider: auditProvider }),
|
|
136
|
+
});
|
|
123
137
|
this.fileWriteInterceptor = new FileWriteInterceptor_1.FileWriteInterceptor(this.config.thresholds.vectorThresholds ?? null);
|
|
124
138
|
// Dedicated lightweight ts-morph project used only for the leading-comment
|
|
125
139
|
// pre-scan. Keeping it separate from the SourceUpdater's project avoids
|
|
@@ -243,6 +257,30 @@ CRITICAL: Do NOT return a CSS selector like "#my-select". Return plain text only
|
|
|
243
257
|
}
|
|
244
258
|
throw directiveErr;
|
|
245
259
|
}
|
|
260
|
+
// ── NO_HEAL cache pre-check ──────────────────────────────────────────
|
|
261
|
+
// If this selector was already identified as an application logic/state
|
|
262
|
+
// failure in this run, skip LLM, DNA load, and DOM extraction entirely.
|
|
263
|
+
// One LLM call pays for 50+ identical state-bug failures in large suites.
|
|
264
|
+
const cachedNoHealReason = this.noHealCache.get(elementSelectorOnly);
|
|
265
|
+
if (cachedNoHealReason !== undefined) {
|
|
266
|
+
logger_1.logger.warn(`[Sela] NO_HEAL cache hit — skipping LLM: ${cachedNoHealReason}`);
|
|
267
|
+
HealReportService_1.sharedHealReport.record({
|
|
268
|
+
kind: "FAILED",
|
|
269
|
+
stableId,
|
|
270
|
+
deterministicKey: (0, HealReportService_1.computeEventDeterministicKey)(reportFile, line, elementSelectorOnly),
|
|
271
|
+
sourceFile: reportFile,
|
|
272
|
+
sourceLine: line,
|
|
273
|
+
testTitle,
|
|
274
|
+
timestamp: new Date().toISOString(),
|
|
275
|
+
framePath: [],
|
|
276
|
+
inIframe: false,
|
|
277
|
+
inShadowDom: false,
|
|
278
|
+
oldSelector: elementSelectorOnly,
|
|
279
|
+
reason: `NO_HEAL (cached) — ${cachedNoHealReason}`,
|
|
280
|
+
dnaBefore: null,
|
|
281
|
+
});
|
|
282
|
+
return "";
|
|
283
|
+
}
|
|
246
284
|
// Snapshot for report event context (loaded once below, used at all exit paths).
|
|
247
285
|
let lastKnownStateForReport = null;
|
|
248
286
|
let aiFixForReport = null;
|
|
@@ -370,6 +408,61 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
|
|
|
370
408
|
});
|
|
371
409
|
}
|
|
372
410
|
aiFixForReport = aiFix;
|
|
411
|
+
// ── NO_HEAL gate ──────────────────────────────────────────────────
|
|
412
|
+
// LLM detected the failure is an application logic/state bug, not
|
|
413
|
+
// selector drift. Surface the native Playwright error without any
|
|
414
|
+
// AST mutation. Populate the noHealCache so subsequent calls for
|
|
415
|
+
// the same selector skip the LLM entirely.
|
|
416
|
+
if (aiFix?.status === "NO_HEAL") {
|
|
417
|
+
const noHealReason = aiFix.reason ?? "LLM detected application logic/state mismatch";
|
|
418
|
+
logger_1.logger.warn(`[Sela] Heal BLOCKED (NO_HEAL): ${noHealReason}`);
|
|
419
|
+
this.noHealCache.set(elementSelectorOnly, noHealReason);
|
|
420
|
+
HealReportService_1.sharedHealReport.record({
|
|
421
|
+
kind: "FAILED",
|
|
422
|
+
stableId,
|
|
423
|
+
deterministicKey: (0, HealReportService_1.computeEventDeterministicKey)(reportFile, line, elementSelectorOnly),
|
|
424
|
+
sourceFile: reportFile,
|
|
425
|
+
sourceLine: line,
|
|
426
|
+
testTitle,
|
|
427
|
+
timestamp: new Date().toISOString(),
|
|
428
|
+
framePath: [],
|
|
429
|
+
inIframe: false,
|
|
430
|
+
inShadowDom: false,
|
|
431
|
+
oldSelector: elementSelectorOnly,
|
|
432
|
+
reason: `NO_HEAL — ${noHealReason}`,
|
|
433
|
+
dnaBefore: (0, HealReportService_1.summariseSnapshot)(lastKnownStateForReport),
|
|
434
|
+
});
|
|
435
|
+
return "";
|
|
436
|
+
}
|
|
437
|
+
// ── Sub-threshold confidence gate ─────────────────────────────────
|
|
438
|
+
// confidence 1–19 = SEMANTIC MISMATCH per the LLM rubric. A proposed
|
|
439
|
+
// selector with near-zero semantic correlation to the original must
|
|
440
|
+
// never reach AST mutation. Record a FailedEvent with the exact reason
|
|
441
|
+
// so CI reports show WHY the heal was blocked.
|
|
442
|
+
if (aiFix?.status === "FIXED" &&
|
|
443
|
+
aiFix.confidence !== undefined &&
|
|
444
|
+
aiFix.confidence < 20) {
|
|
445
|
+
const mismatchReason = `Semantic Mismatch blocked — confidence ${aiFix.confidence}/100 < threshold 20. ` +
|
|
446
|
+
`Proposed: "${aiFix.new_selector ?? "unknown"}". ` +
|
|
447
|
+
`Original intent preserved. Check application state for functional regression.`;
|
|
448
|
+
logger_1.logger.warn(`[Sela] Heal BLOCKED (SEMANTIC_MISMATCH): ${mismatchReason}`);
|
|
449
|
+
HealReportService_1.sharedHealReport.record({
|
|
450
|
+
kind: "FAILED",
|
|
451
|
+
stableId,
|
|
452
|
+
deterministicKey: (0, HealReportService_1.computeEventDeterministicKey)(reportFile, line, elementSelectorOnly),
|
|
453
|
+
sourceFile: reportFile,
|
|
454
|
+
sourceLine: line,
|
|
455
|
+
testTitle,
|
|
456
|
+
timestamp: new Date().toISOString(),
|
|
457
|
+
framePath: [],
|
|
458
|
+
inIframe: false,
|
|
459
|
+
inShadowDom: false,
|
|
460
|
+
oldSelector: elementSelectorOnly,
|
|
461
|
+
reason: `SEMANTIC_MISMATCH — ${mismatchReason}`,
|
|
462
|
+
dnaBefore: (0, HealReportService_1.summariseSnapshot)(lastKnownStateForReport),
|
|
463
|
+
});
|
|
464
|
+
return "";
|
|
465
|
+
}
|
|
373
466
|
if (aiFix && aiFix.status === "FIXED") {
|
|
374
467
|
logger_1.logger.debug("Step 3: AI responded");
|
|
375
468
|
// ── Build new selector ────────────────────────────────────
|
|
@@ -423,6 +516,41 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
|
|
|
423
516
|
else {
|
|
424
517
|
logger_1.logger.debug("Step 3.6: live v2 capture skipped");
|
|
425
518
|
}
|
|
519
|
+
// ── Step 3.7: Visual element screenshot (async write, heal-only) ─
|
|
520
|
+
// Capture is fired here while the page is still stable and the healed
|
|
521
|
+
// selector is confirmed. Disk I/O is non-blocking. The result is
|
|
522
|
+
// attached to the HealedEvent below and, on success, stored in the
|
|
523
|
+
// DNA record so subsequent heals can show the previous baseline.
|
|
524
|
+
const _vsKey = (0, VisualSnapshotService_1.snapshotKey)(filePath, stableId);
|
|
525
|
+
const _vsCandDest = (0, VisualSnapshotService_1.candidateSnapshotPath)(process.cwd(), _vsKey);
|
|
526
|
+
let _vsCapture = { elementFound: false, capturedAt: null };
|
|
527
|
+
let _vsLiveRelPath = null;
|
|
528
|
+
let _vsDnaRelPath = null;
|
|
529
|
+
let _vsDnaCapturedAt = null;
|
|
530
|
+
try {
|
|
531
|
+
_vsCapture = await (0, VisualSnapshotService_1.captureElementScreenshot)(page, elementOnlySelector, successfulPath, _vsCandDest);
|
|
532
|
+
if (_vsCapture.elementFound) {
|
|
533
|
+
const _baselineAbsPath = (0, VisualSnapshotService_1.baselineSnapshotPath)(process.cwd(), _vsKey);
|
|
534
|
+
if (isCiEnvironment()) {
|
|
535
|
+
// CI: keep candidate alongside baseline so the report shows before/after.
|
|
536
|
+
_vsLiveRelPath = path.relative(process.cwd(), _vsCandDest).replace(/\\/g, "/");
|
|
537
|
+
if (fs.existsSync(_baselineAbsPath)) {
|
|
538
|
+
_vsDnaRelPath = path.relative(process.cwd(), _baselineAbsPath).replace(/\\/g, "/");
|
|
539
|
+
_vsDnaCapturedAt = lastKnownState?.visualSnapshot?.capturedAt ?? null;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
// Local: immediately overwrite baseline → only 1 file ever exists.
|
|
544
|
+
(0, VisualSnapshotService_1.promoteCandidateToBaseline)(process.cwd(), _vsKey);
|
|
545
|
+
_vsLiveRelPath = path.relative(process.cwd(), _baselineAbsPath).replace(/\\/g, "/");
|
|
546
|
+
// Before-image is gone (overwritten); suppress the before slot.
|
|
547
|
+
_vsDnaRelPath = null;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
catch {
|
|
552
|
+
// Never block the heal on screenshot failures.
|
|
553
|
+
}
|
|
426
554
|
// ── Safety: delegate all go/no-go decisions to SafetyGuard ─
|
|
427
555
|
const branch = ConfigLoader_1.ConfigLoader.getBranch() ?? undefined;
|
|
428
556
|
const safetyDecision = await this.safetyGuard.evaluate({ mode: healMode, branch }, {
|
|
@@ -837,6 +965,17 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
|
|
|
837
965
|
status: "healed",
|
|
838
966
|
definitionSite: updateResult.definitionSite,
|
|
839
967
|
blastRadius: updateResult.blastRadius,
|
|
968
|
+
// Store the planned dna path so the next heal cycle can read the
|
|
969
|
+
// baseline timestamp. The image is physically at liveSnapshotPath
|
|
970
|
+
// until runCleanRoom() promotes it.
|
|
971
|
+
visualSnapshot: _vsCapture.elementFound && _vsCapture.capturedAt
|
|
972
|
+
? {
|
|
973
|
+
path: path
|
|
974
|
+
.relative(process.cwd(), (0, VisualSnapshotService_1.baselineSnapshotPath)(process.cwd(), _vsKey))
|
|
975
|
+
.replace(/\\/g, "/"),
|
|
976
|
+
capturedAt: _vsCapture.capturedAt,
|
|
977
|
+
}
|
|
978
|
+
: undefined,
|
|
840
979
|
});
|
|
841
980
|
// ── Report: HEALED event ───────────────────────────────────────
|
|
842
981
|
const healedEvent = {
|
|
@@ -878,6 +1017,13 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
|
|
|
878
1017
|
definitionSite: updateResult.definitionSite,
|
|
879
1018
|
contentChange: aiFix.contentChange,
|
|
880
1019
|
confidenceVectors: safetyDecision.meta?.confidenceVectors,
|
|
1020
|
+
visualDiff: {
|
|
1021
|
+
dnaSnapshotPath: _vsDnaRelPath,
|
|
1022
|
+
liveSnapshotPath: _vsLiveRelPath,
|
|
1023
|
+
dnaSnapshotCapturedAt: _vsDnaCapturedAt,
|
|
1024
|
+
liveSnapshotCapturedAt: _vsCapture.capturedAt,
|
|
1025
|
+
elementFound: _vsCapture.elementFound,
|
|
1026
|
+
},
|
|
881
1027
|
};
|
|
882
1028
|
HealReportService_1.sharedHealReport.record(healedEvent);
|
|
883
1029
|
// ── Cache write - persist this safe heal for future sessions ──
|
|
@@ -1378,7 +1524,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
|
|
|
1378
1524
|
// Replaces the previous DOMUtils.getElementDNA() path with a single
|
|
1379
1525
|
// captureElement() call that collects all v2 metrics atomically.
|
|
1380
1526
|
// ─────────────────────────────────────────────────────────────
|
|
1381
|
-
async captureSuccessfulElement(page, selector, stableId) {
|
|
1527
|
+
async captureSuccessfulElement(page, selector, stableId, sourceFile) {
|
|
1382
1528
|
try {
|
|
1383
1529
|
const snapshot = await this.snapshotService.captureElement(page, selector);
|
|
1384
1530
|
if (snapshot) {
|
|
@@ -1390,11 +1536,55 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
|
|
|
1390
1536
|
};
|
|
1391
1537
|
this.dnaBuffer.set(stableId, enriched);
|
|
1392
1538
|
logger_1.logger.debug(`DNA v2 captured for: ${stableId}`);
|
|
1539
|
+
// ── Visual baseline capture (guarded) ─────────────────────
|
|
1540
|
+
// Local only: capture a PNG baseline when the file is missing or the
|
|
1541
|
+
// DOM snapshot changed. CI is read-only — baselines are committed
|
|
1542
|
+
// from local dev and must not be regenerated during CI test runs.
|
|
1543
|
+
if (sourceFile && !isCiEnvironment()) {
|
|
1544
|
+
try {
|
|
1545
|
+
const vsKey = (0, VisualSnapshotService_1.snapshotKey)(sourceFile, stableId);
|
|
1546
|
+
const baseDest = (0, VisualSnapshotService_1.baselineSnapshotPath)(process.cwd(), vsKey);
|
|
1547
|
+
const baseStat = fs.existsSync(baseDest) ? fs.statSync(baseDest) : null;
|
|
1548
|
+
const pngMissing = !baseStat || baseStat.size === 0;
|
|
1549
|
+
let needsCapture = pngMissing;
|
|
1550
|
+
if (!pngMissing) {
|
|
1551
|
+
// load() reads from disk — commitUpdates() hasn't run yet,
|
|
1552
|
+
// so this returns the snapshot from the PREVIOUS run.
|
|
1553
|
+
const prevSnap = await this.snapshotService.load(stableId);
|
|
1554
|
+
needsCapture =
|
|
1555
|
+
!prevSnap ||
|
|
1556
|
+
SelaEngine._snapshotFingerprint(prevSnap) !==
|
|
1557
|
+
SelaEngine._snapshotFingerprint(enriched);
|
|
1558
|
+
}
|
|
1559
|
+
if (needsCapture) {
|
|
1560
|
+
const candDest = (0, VisualSnapshotService_1.candidateSnapshotPath)(process.cwd(), vsKey);
|
|
1561
|
+
const result = await (0, VisualSnapshotService_1.captureElementScreenshot)(page, selector, [], candDest);
|
|
1562
|
+
if (result.elementFound) {
|
|
1563
|
+
(0, VisualSnapshotService_1.promoteCandidateToBaseline)(process.cwd(), vsKey);
|
|
1564
|
+
logger_1.logger.debug(`Visual baseline ${pngMissing ? "created" : "refreshed"}: ${vsKey}`);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
catch (vsErr) {
|
|
1569
|
+
logger_1.logger.debug(`Visual baseline skipped: ${vsErr.message}`);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1393
1572
|
}
|
|
1394
1573
|
}
|
|
1395
1574
|
catch (error) {
|
|
1396
1575
|
logger_1.logger.debug(`DNA capture skipped: ${error.message}`);
|
|
1397
1576
|
}
|
|
1398
1577
|
}
|
|
1578
|
+
// Stable fingerprint of DOM-visible fields only (excludes timestamps, rect,
|
|
1579
|
+
// and metadata). Used to decide whether the visual PNG baseline needs refresh.
|
|
1580
|
+
static _snapshotFingerprint(s) {
|
|
1581
|
+
return JSON.stringify({
|
|
1582
|
+
tagName: s.tagName,
|
|
1583
|
+
text: s.text,
|
|
1584
|
+
role: s.role,
|
|
1585
|
+
classes: [...(s.classes ?? [])].sort(),
|
|
1586
|
+
attributes: Object.fromEntries(Object.entries(s.attributes ?? {}).sort()),
|
|
1587
|
+
});
|
|
1588
|
+
}
|
|
1399
1589
|
}
|
|
1400
1590
|
exports.SelaEngine = SelaEngine;
|
|
@@ -150,4 +150,11 @@ export declare const CHAIN_VALIDATOR_CODES: {
|
|
|
150
150
|
readonly SEMANTIC_DOWNGRADE: "CV_SEMANTIC_DOWNGRADE";
|
|
151
151
|
};
|
|
152
152
|
export type ChainValidatorCode = (typeof CHAIN_VALIDATOR_CODES)[keyof typeof CHAIN_VALIDATOR_CODES];
|
|
153
|
+
export declare const ENGINE_CODES: {
|
|
154
|
+
/** LLM determined the failure is an application logic/state bug, not selector drift. */
|
|
155
|
+
readonly NO_HEAL_APP_LOGIC: "ENG_NO_HEAL_APP_LOGIC";
|
|
156
|
+
/** LLM returned a selector containing dynamic expressions — static-output contract violated. */
|
|
157
|
+
readonly DYNAMIC_OUTPUT_BLOCKED: "ENG_DYNAMIC_OUTPUT_BLOCKED";
|
|
158
|
+
};
|
|
159
|
+
export type EngineCode = (typeof ENGINE_CODES)[keyof typeof ENGINE_CODES];
|
|
153
160
|
//# sourceMappingURL=SelaError.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelaError.d.ts","sourceRoot":"","sources":["../../src/errors/SelaError.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,eAAe,GACf,YAAY,GACZ,OAAO,GACP,YAAY,GACZ,UAAU,GACV,gBAAgB,GAChB,QAAQ,GACR,QAAQ,CAAC;AAMb,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,iBAAiB,GAAG,MAAM,CAAC;IACnE,0EAA0E;IAC1E,cAAc,CAAC,EAAE,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;IAC9D,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAMD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,aAAa,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,aAAa,CAAC;IACzB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAYD,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;gBAEvB,IAAI,EAAE,aAAa;IAsC/B,MAAM,CAAC,aAAa,CAClB,SAAS,EAAE,aAAa,EACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM;IAIT,MAAM,IAAI,aAAa;CAexB;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,SAAS,CAE1D;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,aAAa,GACvB,GAAG,IAAI,SAAS,CAElB;AAUD,eAAO,MAAM,kBAAkB;;;;;;;;;IAS7B;;iEAE6D;;IAE7D;;;;OAIG;;IAEH,+EAA+E;;IAE/E;uFACmF;;CAE3E,CAAC;AACX,MAAM,MAAM,eAAe,GACzB,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAE/D,eAAO,MAAM,oBAAoB;IAC/B,wEAAwE;;;;CAIhE,CAAC;AACX,MAAM,MAAM,iBAAiB,GAC3B,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,OAAO,oBAAoB,CAAC,CAAC;AAEnE,eAAO,MAAM,iBAAiB;;;;;;CAMpB,CAAC;AACX,MAAM,MAAM,cAAc,GACxB,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAE7D,eAAO,MAAM,iBAAiB;;;;;;;IAO5B;;;;OAIG;;CAEK,CAAC;AACX,MAAM,MAAM,cAAc,GACxB,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAE7D,eAAO,MAAM,WAAW;;;;CAId,CAAC;AACX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEvE,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAEhF,eAAO,MAAM,YAAY;IACvB,2EAA2E;;IAE3E,wDAAwD;;IAExD,gEAAgE;;IAEhE,gDAAgD;;IAEhD,8CAA8C;;IAE9C;;;;OAIG;;IAEH,gFAAgF;;CAExE,CAAC;AACX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE1E,eAAO,MAAM,qBAAqB;;;;;;CAMxB,CAAC;AACX,MAAM,MAAM,kBAAkB,GAC5B,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,OAAO,qBAAqB,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"SelaError.d.ts","sourceRoot":"","sources":["../../src/errors/SelaError.ts"],"names":[],"mappings":"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"}
|
package/dist/errors/SelaError.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// Public message regex (used by tests/unit/engine/error-indicativity.test.ts):
|
|
14
14
|
// /^\[Sela-(SafetyGuard|IntentAuditor|ASTUpdater|Proxy|LLMService|Registry|ChainValidator|Engine)\] [A-Z][A-Z0-9_]+: .+$/
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.CHAIN_VALIDATOR_CODES = exports.REPORT_CODES = exports.REGISTRY_CODES = exports.PROXY_CODES = exports.AST_UPDATER_CODES = exports.LLM_SERVICE_CODES = exports.INTENT_AUDITOR_CODES = exports.SAFETY_GUARD_CODES = exports.SelaError = void 0;
|
|
16
|
+
exports.ENGINE_CODES = exports.CHAIN_VALIDATOR_CODES = exports.REPORT_CODES = exports.REGISTRY_CODES = exports.PROXY_CODES = exports.AST_UPDATER_CODES = exports.LLM_SERVICE_CODES = exports.INTENT_AUDITOR_CODES = exports.SAFETY_GUARD_CODES = exports.SelaError = void 0;
|
|
17
17
|
exports.isSelaError = isSelaError;
|
|
18
18
|
exports.isSelaErrorFrom = isSelaErrorFrom;
|
|
19
19
|
// ───────────────────────────────────────────────────────────────────
|
|
@@ -173,3 +173,9 @@ exports.CHAIN_VALIDATOR_CODES = {
|
|
|
173
173
|
PLACEMENT: "CV_PLACEMENT",
|
|
174
174
|
SEMANTIC_DOWNGRADE: "CV_SEMANTIC_DOWNGRADE",
|
|
175
175
|
};
|
|
176
|
+
exports.ENGINE_CODES = {
|
|
177
|
+
/** LLM determined the failure is an application logic/state bug, not selector drift. */
|
|
178
|
+
NO_HEAL_APP_LOGIC: "ENG_NO_HEAL_APP_LOGIC",
|
|
179
|
+
/** LLM returned a selector containing dynamic expressions — static-output contract violated. */
|
|
180
|
+
DYNAMIC_OUTPUT_BLOCKED: "ENG_DYNAMIC_OUTPUT_BLOCKED",
|
|
181
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixtures/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAK/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixtures/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAK/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAuCpD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAI/D;AAgoBD,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,GAAG,EACpB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,IAAI,EACb,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAChC,WAAW,EAAE,MAAM,GAClB,GAAG,CAuCL;AAaD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,OAAO,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,IAAI,EACb,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAChC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,GAAG,CAiPL;AAQD,eAAO,MAAM,IAAI;YAEL,UAAU,CAAC,OAAO,mBAAmB,CAAC;;IAG9C;;;;;;;;;;;;;OAaG;0BACmB,IAAI;EAmI5B,CAAC;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/fixtures/index.js
CHANGED
|
@@ -58,11 +58,12 @@ function regressionInjector() {
|
|
|
58
58
|
if (_regressionInjector !== undefined)
|
|
59
59
|
return _regressionInjector;
|
|
60
60
|
const active = process.env["SELA_REGRESSION_ACTIVE"];
|
|
61
|
-
|
|
62
|
-
if (active?.trim().toLowerCase() !== "true" || !manifestPath) {
|
|
61
|
+
if (active?.trim().toLowerCase() !== "true") {
|
|
63
62
|
_regressionInjector = null;
|
|
64
63
|
return null;
|
|
65
64
|
}
|
|
65
|
+
const manifestPath = process.env["SELA_REGRESSION_MANIFEST"] ??
|
|
66
|
+
path.join(process.cwd(), ".sela", RegressionManifestService_1.REGRESSION_MANIFEST_FILE);
|
|
66
67
|
try {
|
|
67
68
|
_regressionInjector = RegressionManifestService_1.RegressionInjector.fromFile(manifestPath);
|
|
68
69
|
logger_1.logger.debug(`Shadow-regression injector loaded from ${manifestPath}`);
|
|
@@ -325,7 +326,7 @@ async function runWithHeal(rawPage, prop, args, fullSelector, elementSelectorOnl
|
|
|
325
326
|
// can pass an explicit timeout in their test code; buildHealedArgs
|
|
326
327
|
// respects an existing timeout object if present.
|
|
327
328
|
const callArgs = buildHealedArgs(prop, args, 3000);
|
|
328
|
-
await singleton_1.sharedEngine.captureSuccessfulElement(rawPage, effectiveSelector, stableId);
|
|
329
|
+
await singleton_1.sharedEngine.captureSuccessfulElement(rawPage, effectiveSelector, stableId, callerInfo.filePath);
|
|
329
330
|
const result = await initialLocator[prop](...callArgs);
|
|
330
331
|
return {
|
|
331
332
|
result,
|
|
@@ -376,7 +377,7 @@ async function runWithHealSelector(rawPage, prop, args, fullSelector, elementSel
|
|
|
376
377
|
// We just need to build the locator for THIS call-site's retry.
|
|
377
378
|
const healedLocator = buildLiveLocator(rawPage, newFullSelector);
|
|
378
379
|
try {
|
|
379
|
-
await singleton_1.sharedEngine.captureSuccessfulElement(rawPage, newFullSelector, stableId);
|
|
380
|
+
await singleton_1.sharedEngine.captureSuccessfulElement(rawPage, newFullSelector, stableId, callerInfo.filePath);
|
|
380
381
|
const result = await healedLocator[prop](...buildHealedArgs(prop, args, 8000));
|
|
381
382
|
return {
|
|
382
383
|
result,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
2
|
+
import type { LLMProvider, CompletionParams } from "./LLMProvider";
|
|
3
|
+
export declare class AnthropicProvider implements LLMProvider {
|
|
4
|
+
private readonly modelId;
|
|
5
|
+
private readonly client;
|
|
6
|
+
constructor(modelId: string, apiKeyOrClient: string | Anthropic);
|
|
7
|
+
complete(params: CompletionParams): Promise<string>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=AnthropicProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnthropicProvider.d.ts","sourceRoot":"","sources":["../../src/providers/AnthropicProvider.ts"],"names":[],"mappings":"AAKA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,qBAAa,iBAAkB,YAAW,WAAW;IAIjD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAH1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;gBAGhB,OAAO,EAAE,MAAM,EAChC,cAAc,EAAE,MAAM,GAAG,SAAS;IAQ9B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;CAU1D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/providers/AnthropicProvider.ts
|
|
3
|
+
// LLMProvider adapter for the Anthropic SDK (@anthropic-ai/sdk).
|
|
4
|
+
// Accepts either an API key string (creates a fresh client) or a pre-built
|
|
5
|
+
// Anthropic instance (used by legacy code-paths and tests that inject a mock).
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.AnthropicProvider = void 0;
|
|
11
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
12
|
+
class AnthropicProvider {
|
|
13
|
+
modelId;
|
|
14
|
+
client;
|
|
15
|
+
constructor(modelId, apiKeyOrClient) {
|
|
16
|
+
this.modelId = modelId;
|
|
17
|
+
this.client =
|
|
18
|
+
typeof apiKeyOrClient === "string"
|
|
19
|
+
? new sdk_1.default({ apiKey: apiKeyOrClient })
|
|
20
|
+
: apiKeyOrClient;
|
|
21
|
+
}
|
|
22
|
+
async complete(params) {
|
|
23
|
+
const msg = await this.client.messages.create({
|
|
24
|
+
model: this.modelId,
|
|
25
|
+
max_tokens: params.maxTokens ?? 1024,
|
|
26
|
+
...(params.temperature !== undefined && { temperature: params.temperature }),
|
|
27
|
+
system: params.system,
|
|
28
|
+
messages: params.messages,
|
|
29
|
+
});
|
|
30
|
+
return msg.content[0]?.type === "text" ? msg.content[0].text : "";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.AnthropicProvider = AnthropicProvider;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CompletionParams {
|
|
2
|
+
system?: string;
|
|
3
|
+
messages: Array<{
|
|
4
|
+
role: "user" | "assistant";
|
|
5
|
+
content: string;
|
|
6
|
+
}>;
|
|
7
|
+
maxTokens?: number;
|
|
8
|
+
temperature?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface LLMProvider {
|
|
11
|
+
complete(params: CompletionParams): Promise<string>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=LLMProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LLMProvider.d.ts","sourceRoot":"","sources":["../../src/providers/LLMProvider.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/providers/LLMProvider.ts
|
|
3
|
+
// Provider-agnostic interface for LLM text completion.
|
|
4
|
+
// All AI calls in Sela (healing + intent audit) route through this contract
|
|
5
|
+
// so the engine never cares whether it's talking to Claude, GPT-4o, or a
|
|
6
|
+
// self-hosted local model behind an OpenAI-compatible endpoint.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LLMProvider, CompletionParams } from "./LLMProvider";
|
|
2
|
+
export declare class OpenAICompatibleProvider implements LLMProvider {
|
|
3
|
+
private readonly modelId;
|
|
4
|
+
private readonly client;
|
|
5
|
+
constructor(modelId: string, apiKey: string, baseUrl?: string, customHeaders?: Record<string, string>, disableSslVerification?: boolean, timeoutMs?: number);
|
|
6
|
+
complete(params: CompletionParams): Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=OpenAICompatibleProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenAICompatibleProvider.d.ts","sourceRoot":"","sources":["../../src/providers/OpenAICompatibleProvider.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,qBAAa,wBAAyB,YAAW,WAAW;IAIxD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAH1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAGb,OAAO,EAAE,MAAM,EAChC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACtC,sBAAsB,CAAC,EAAE,OAAO,EAChC,SAAS,CAAC,EAAE,MAAM;IAgBd,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;CAmB1D"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/providers/OpenAICompatibleProvider.ts
|
|
3
|
+
// LLMProvider adapter for any OpenAI-compatible HTTP endpoint.
|
|
4
|
+
// Covers: OpenAI SaaS, local LM Studio / Ollama, vLLM, Together AI,
|
|
5
|
+
// and air-gapped internal clusters reachable at a custom base URL.
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.OpenAICompatibleProvider = void 0;
|
|
11
|
+
const openai_1 = __importDefault(require("openai"));
|
|
12
|
+
const https_1 = __importDefault(require("https"));
|
|
13
|
+
class OpenAICompatibleProvider {
|
|
14
|
+
modelId;
|
|
15
|
+
client;
|
|
16
|
+
constructor(modelId, apiKey, baseUrl, customHeaders, disableSslVerification, timeoutMs) {
|
|
17
|
+
this.modelId = modelId;
|
|
18
|
+
this.client = new openai_1.default({
|
|
19
|
+
// Local servers often have no real key — "local" is a safe sentinel.
|
|
20
|
+
apiKey: apiKey || "local",
|
|
21
|
+
baseURL: baseUrl,
|
|
22
|
+
defaultHeaders: customHeaders,
|
|
23
|
+
...(timeoutMs !== undefined && { timeout: timeoutMs }),
|
|
24
|
+
// Air-gapped corporate proxies may use self-signed certs.
|
|
25
|
+
// Only skip verification when the user explicitly opts in.
|
|
26
|
+
...(disableSslVerification && {
|
|
27
|
+
httpAgent: new https_1.default.Agent({ rejectUnauthorized: false }),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async complete(params) {
|
|
32
|
+
const messages = [];
|
|
33
|
+
if (params.system) {
|
|
34
|
+
messages.push({ role: "system", content: params.system });
|
|
35
|
+
}
|
|
36
|
+
for (const m of params.messages) {
|
|
37
|
+
messages.push({ role: m.role, content: m.content });
|
|
38
|
+
}
|
|
39
|
+
const res = await this.client.chat.completions.create({
|
|
40
|
+
model: this.modelId,
|
|
41
|
+
max_tokens: params.maxTokens ?? 1024,
|
|
42
|
+
...(params.temperature !== undefined && { temperature: params.temperature }),
|
|
43
|
+
messages,
|
|
44
|
+
});
|
|
45
|
+
return res.choices[0]?.message?.content ?? "";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.OpenAICompatibleProvider = OpenAICompatibleProvider;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { LLMProvider } from "./LLMProvider";
|
|
2
|
+
import type { ResolvedLLMModelConfig, ResolvedSanitization } from "../config/SelaConfig";
|
|
3
|
+
export declare function createProvider(cfg: ResolvedLLMModelConfig, sanitization?: ResolvedSanitization): LLMProvider;
|
|
4
|
+
//# sourceMappingURL=ProviderFactory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProviderFactory.d.ts","sourceRoot":"","sources":["../../src/providers/ProviderFactory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAIjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIzF,wBAAgB,cAAc,CAC5B,GAAG,EAAE,sBAAsB,EAC3B,YAAY,CAAC,EAAE,oBAAoB,GAClC,WAAW,CAab"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/providers/ProviderFactory.ts
|
|
3
|
+
// Single entry-point for constructing LLMProvider instances from config.
|
|
4
|
+
// Wraps the created provider in SanitizingProvider when PII masking is enabled.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createProvider = createProvider;
|
|
7
|
+
const AnthropicProvider_1 = require("./AnthropicProvider");
|
|
8
|
+
const OpenAICompatibleProvider_1 = require("./OpenAICompatibleProvider");
|
|
9
|
+
const SanitizingProvider_1 = require("./SanitizingProvider");
|
|
10
|
+
const Sanitizer_1 = require("../services/Sanitizer");
|
|
11
|
+
const SelaError_1 = require("../errors/SelaError");
|
|
12
|
+
function createProvider(cfg, sanitization) {
|
|
13
|
+
const inner = buildInnerProvider(cfg);
|
|
14
|
+
if (!sanitization || !sanitization.enabled)
|
|
15
|
+
return inner;
|
|
16
|
+
const patterns = (0, Sanitizer_1.compileCustomPatterns)(sanitization.customPatterns ?? []);
|
|
17
|
+
const scrub = (s) => (0, Sanitizer_1.sanitizeText)(s, {
|
|
18
|
+
redactInputValues: sanitization.redactInputValues,
|
|
19
|
+
customPatterns: patterns,
|
|
20
|
+
});
|
|
21
|
+
return new SanitizingProvider_1.SanitizingProvider(inner, scrub);
|
|
22
|
+
}
|
|
23
|
+
function buildInnerProvider(cfg) {
|
|
24
|
+
switch (cfg.provider) {
|
|
25
|
+
case "anthropic": {
|
|
26
|
+
// Fall back to process.env at provider-construction time so SelaEngine
|
|
27
|
+
// integration tests that stub ConfigLoader with an empty env still work,
|
|
28
|
+
// and so that legacy `ANTHROPIC_API_KEY` env usage is preserved.
|
|
29
|
+
const key = cfg.apiKey || process.env.ANTHROPIC_API_KEY || "";
|
|
30
|
+
if (!key) {
|
|
31
|
+
throw new SelaError_1.SelaError({
|
|
32
|
+
subsystem: "LLMService",
|
|
33
|
+
code: SelaError_1.LLM_SERVICE_CODES.NO_API_KEY,
|
|
34
|
+
reason: "No API key for Anthropic provider. Set ANTHROPIC_API_KEY or provide llm.healingModel.apiKey in sela.config.ts.",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return new AnthropicProvider_1.AnthropicProvider(cfg.modelId, key);
|
|
38
|
+
}
|
|
39
|
+
case "openai":
|
|
40
|
+
case "openai-compatible":
|
|
41
|
+
case "local":
|
|
42
|
+
return new OpenAICompatibleProvider_1.OpenAICompatibleProvider(cfg.modelId, cfg.apiKey, cfg.baseUrl, cfg.customHeaders, cfg.disableSslVerification, cfg.timeoutMs);
|
|
43
|
+
default:
|
|
44
|
+
throw new SelaError_1.SelaError({
|
|
45
|
+
subsystem: "LLMService",
|
|
46
|
+
code: SelaError_1.LLM_SERVICE_CODES.NO_API_KEY,
|
|
47
|
+
reason: `Unknown LLM provider: "${cfg.provider}". Valid values: anthropic, openai, openai-compatible, local.`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LLMProvider, CompletionParams } from "./LLMProvider";
|
|
2
|
+
export declare class SanitizingProvider implements LLMProvider {
|
|
3
|
+
private readonly inner;
|
|
4
|
+
private readonly scrub;
|
|
5
|
+
constructor(inner: LLMProvider, scrub: (s: string) => string);
|
|
6
|
+
complete(params: CompletionParams): Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=SanitizingProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SanitizingProvider.d.ts","sourceRoot":"","sources":["../../src/providers/SanitizingProvider.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,qBAAa,kBAAmB,YAAW,WAAW;IAElD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM;IAGzC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;CAU1D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/providers/SanitizingProvider.ts
|
|
3
|
+
// LLMProvider decorator that scrubs PII/secrets from every outbound
|
|
4
|
+
// completion request before delegating to the inner provider.
|
|
5
|
+
// This is the provider-layer equivalent of the legacy SanitizingAnthropic
|
|
6
|
+
// wrapper — same guarantee, not tied to any specific SDK.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.SanitizingProvider = void 0;
|
|
9
|
+
class SanitizingProvider {
|
|
10
|
+
inner;
|
|
11
|
+
scrub;
|
|
12
|
+
constructor(inner, scrub) {
|
|
13
|
+
this.inner = inner;
|
|
14
|
+
this.scrub = scrub;
|
|
15
|
+
}
|
|
16
|
+
async complete(params) {
|
|
17
|
+
return this.inner.complete({
|
|
18
|
+
...params,
|
|
19
|
+
system: params.system !== undefined ? this.scrub(params.system) : undefined,
|
|
20
|
+
messages: params.messages.map((m) => ({
|
|
21
|
+
...m,
|
|
22
|
+
content: this.scrub(m.content),
|
|
23
|
+
})),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.SanitizingProvider = SanitizingProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ASTSourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/ASTSourceUpdater.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQ/C,OAAO,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAOjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAmB,YAAY,
|
|
1
|
+
{"version":3,"file":"ASTSourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/ASTSourceUpdater.ts"],"names":[],"mappings":"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"}
|