feat: Enhance provider components with detailed documentation and comments

- Added comprehensive comments and JSDoc-style documentation to NotificationProvider, ThemeProvider, UserProvider, and WebsiteThemeProvider for better clarity and maintainability.
- Improved type definitions in index.ts for better code understanding and usage.
- Introduced Docker support with Dockerfiles for various services including AI server, signaling server, and browser-use service.
- Created a docker-compose.yml file to orchestrate multiple services including PostgreSQL, AI, scraper, and frontend.
- Added a startup guide (startup.txt) for setting up the CRM environment on Ubuntu with Docker.
- Included a .dockerignore file to exclude unnecessary files from Docker builds.
This commit is contained in:
Ace
2026-07-13 13:05:30 +02:00
parent dba4c84cd5
commit d35c806d5b
167 changed files with 3474 additions and 102 deletions
+17 -1
View File
@@ -28,19 +28,23 @@ import { createRequire } from "node:module"
const SELF = dirname(fileURLToPath(import.meta.url))
const _require = createRequire(import.meta.url)
const ROOT = resolve(SELF, "..")
// Ollama endpoint and model can be overridden via environment variables
const OLLAMA_HOST = process.env.OLLAMA_HOST || "http://localhost:11434"
const MODEL = process.env.REPAIR_MODEL || "qwen2.5-coder:1.5b-base"
// Safety limits: max repair iterations, minimum AI confidence to auto-apply, escalation timeout
const MAX_ITERATIONS = 5
const CONFIDENCE_THRESHOLD = 0.7
const ESCALATION_TIMEOUT_MS = 30 * 60 * 1000 // 30 min
// ── Helpers ────────────────────────────────────────────────────────
/** Log a message with a level-based prefix for visual scanning of output. */
function log(msg, level = "info") {
const prefix = level === "error" ? "✗" : level === "warn" ? "⚠" : "✓"
console.log(` ${prefix} [repair] ${msg}`)
}
/** Run `npx tsc --noEmit` and return the output (success or failure). */
function runTsc() {
try {
const out = execSync("npx tsc --noEmit", { stdio: "pipe", timeout: 60000, cwd: ROOT })
@@ -50,6 +54,7 @@ function runTsc() {
}
}
/** Parse TypeScript compiler output into structured error objects with file, line, column, and message. */
function parseErrors(output) {
const errors = []
// Match: src/file.ts(line,col): error TSxxxx: message
@@ -66,6 +71,7 @@ function parseErrors(output) {
return errors
}
/** Read source file lines surrounding the error, returning a snippet with context line offset. */
function readContext(filePath, errorLine, contextLines = 20) {
try {
const lines = readFileSync(filePath, "utf-8").split("\n")
@@ -83,6 +89,7 @@ function readContext(filePath, errorLine, contextLines = 20) {
// ── Ollama Integration ─────────────────────────────────────────────
/** Send a repair prompt to the Ollama model and return the raw response text. */
async function queryOllama(prompt) {
const response = await fetch(`${OLLAMA_HOST}/api/generate`, {
method: "POST",
@@ -99,6 +106,7 @@ async function queryOllama(prompt) {
return data.response || ""
}
/** Build a structured prompt for the AI model, including file path, error message, and surrounding code context. */
function buildRepairPrompt(filePath, errorMessage, codeContext) {
return `You are a TypeScript repair agent. Fix the following error.
@@ -122,6 +130,7 @@ Rules:
- If you cannot determine a fix, set confidence to 0`
}
/** Parse the AI's JSON response (handles optional markdown fences around the JSON block). */
function parseFixResponse(text) {
try {
// Extract JSON from response (it might have markdown fences)
@@ -133,6 +142,7 @@ function parseFixResponse(text) {
}
}
/** Apply a fix suggestion to disk, returning success/failure and a backup of the original content. */
function applyFix(filePath, fixSuggestion) {
if (!fixSuggestion || !fixSuggestion.fix) return { applied: false, reason: "No fix suggestion" }
@@ -147,8 +157,8 @@ function applyFix(filePath, fixSuggestion) {
// ── Breaking Change Escalation ─────────────────────────────────────
/** Heuristic check: if any fix touches imports, exports, or deletions, consider it a breaking change. */
function isBreakingChange(errors, fixes) {
// Heuristic: if fix touches import structure or exports, it's breaking
for (const fix of fixes) {
if (!fix || !fix.fix) continue
if (fix.fix.includes("export ") || fix.fix.includes("import ") || fix.fix.includes("delete ")) {
@@ -158,6 +168,7 @@ function isBreakingChange(errors, fixes) {
return false
}
/** Log the breaking change, wait for the escalation timeout, then auto-apply. */
async function escalateBreakingChange(errors, fixes) {
const logFile = resolve(ROOT, "repair-escalation.log")
const timestamp = new Date().toISOString()
@@ -181,6 +192,7 @@ async function escalateBreakingChange(errors, fixes) {
// ── Git Auto-Commit ────────────────────────────────────────────────
/** Git commit all changes with a [bot]-prefixed message. Returns false on failure (non-blocking). */
function gitCommit(message) {
try {
execSync("git add -A", { stdio: "pipe", cwd: ROOT })
@@ -195,6 +207,7 @@ function gitCommit(message) {
// ── Main Repair Loop ───────────────────────────────────────────────
/** Single pass: run tsc, parse errors, ask AI for fixes, apply them, and verify. Returns result summary. */
async function repairOnce(doCommit = false) {
log("Running build check...")
const build = runTsc()
@@ -276,6 +289,7 @@ async function repairOnce(doCommit = false) {
return { fixed: remainingErrors.length === 0, errors: remainingErrors, fixes }
}
/** Run up to maxIterations repair passes, stopping once all errors are resolved or no progress is made. */
async function repairLoop(maxIterations = MAX_ITERATIONS, doCommit = false) {
for (let i = 0; i < maxIterations; i++) {
log(`=== Repair iteration ${i + 1}/${maxIterations} ===`)
@@ -293,8 +307,10 @@ async function repairLoop(maxIterations = MAX_ITERATIONS, doCommit = false) {
// ── Watch Mode ─────────────────────────────────────────────────────
/** Watch mode: monitor src/ for file changes and auto-repair errors. Falls back to polling if chokidar is unavailable. */
function watchMode() {
log("Watch mode active — monitoring src/ for changes...", "info")
// Try loading chokidar; if not installed, fall back to simple interval polling
const chokidar = (() => {
try {
return _require("chokidar")