feat: AI intent router live + TOTP repeat-auth fix
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s

AI Intent Router:
- Wired /api/v1/ai/intent and /api/v1/ai/capabilities into app.js
- Pattern matching works offline, no API key needed
- Handles: deploy, recommend, diagnose, backup, health, list
- AI chat floating button on dashboard (🤖)
- Suggestion chips: Deploy Plex, Stream movies, Block ads, System health
- Deploy buttons in chat launch the app selector

TOTP Fix:
- secureFetch() was missing credentials: same-origin
- Session cookie was not being sent on API calls
- Added credentials: same-origin to all fetch calls
- Users no longer prompted for TOTP on every action

Nesting Guard:
- Fixed logging module path (../utils/logging not ./logging)
- Switched to console.log to avoid module export mismatch

MCP Server:
- 551-line JSON-RPC server ready at src/mcp/mcp-server.js
- Configurable via DASHCADDY_URL + DASHCADDY_API_KEY env vars
This commit is contained in:
Krystie
2026-08-13 03:33:28 -07:00
parent d25343000f
commit 3da8463cef
7 changed files with 180 additions and 10 deletions
+2
View File
@@ -95,6 +95,7 @@ const workflowsRoutes = require('../routes/workflows');
const dependenciesRoutes = require('../routes/dependencies');
const securityRoutes = require('../routes/security');
const diskSettingsRoutes = require('../routes/disk-settings');
const aiIntentRoutes = require('../routes/ai-intent');
const logInsightsRoutes = require('../routes/log-insights');
const billingRoutes = require('../routes/billing');
const DependencyManager = require('./managers/dependency-manager');
@@ -759,6 +760,7 @@ async function createApp() {
// Log Insights — plain English activity summary + safe log disposal
apiRouter.use('/disk-settings', diskSettingsRoutes);
apiRouter.use(aiIntentRoutes({ asyncHandler: ctx.asyncHandler }));
apiRouter.use(logInsightsRoutes({
asyncHandler: ctx.asyncHandler,
ok: ctx.ok,
+1 -1
View File
@@ -483,7 +483,7 @@ const DEFAULT_LANGUAGE = 'en';
// Language metadata for UI dropdowns
const LANGUAGE_META = {
en: { name: 'English', flag: '🇬🇧', rtl: false },
en: { name: 'English', flag: '🇺🇸', rtl: false },
ar: { name: 'العربية', flag: '🇸🇦', rtl: true },
bn: { name: 'বাংলা', flag: '🇧🇩', rtl: false },
cs: { name: 'Čeština', flag: '🇨🇿', rtl: false },
+5 -8
View File
@@ -10,11 +10,11 @@
const fs = require('fs');
const path = require('path');
const log = require('./logging');
module.exports = function nestingGuard() {
try {
const dataDir = require('../config/paths').dataDir;
const paths = require('../config/paths');
const dataDir = paths.dataDir;
const dataDataPath = path.join(dataDir, 'data');
// If data/data exists, it's a recursive duplicate — remove it
@@ -25,17 +25,14 @@ module.exports = function nestingGuard() {
const markerFile = path.join(dataDataPath, 'config.json');
const parentMarker = path.join(dataDir, 'config.json');
if (fs.existsSync(markerFile) && fs.existsSync(parentMarker)) {
const size = require('child_process')
.execSync(`du -sh '${dataDataPath}' 2>/dev/null | cut -f1`)
.toString().trim();
log.warn('startup', `Removing recursive data nesting: ${dataDataPath} (${size})`);
console.log('[nesting-guard] Removing recursive data nesting: ' + dataDataPath);
fs.rmSync(dataDataPath, { recursive: true, force: true });
log.info('startup', 'Recursive nesting removed');
console.log('[nesting-guard] Recursive nesting removed');
}
}
}
} catch (e) {
// Non-fatal — don't crash startup over cleanup
log.warn('startup', `Nesting guard skipped: ${e.message}`);
console.warn('[nesting-guard] Skipped: ' + e.message);
}
};