Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 37 additions & 37 deletions apps/api/agents/langgraph/PromptProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,28 @@
*/

import fs from 'fs';
import path, { dirname } from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

import path from 'path';

// Import required utilities
import { enrichRequest } from '../../utils/requestEnrichment.js';
import { assemblePromptGraphAsync } from './promptAssemblyGraph.js';
import { sendSuccessResponseWithAttachments } from '../../utils/request/index.js';
import {
localizePromptObject,
extractLocaleFromRequest,
} from '../../services/localization/index.js';
import { withErrorHandler, handleValidationError } from '../../utils/errors/index.js';
import { processAutomatischPR } from './PRAgent/index.js';
import {
MARKDOWN_FORMATTING_INSTRUCTIONS,
HTML_FORMATTING_INSTRUCTIONS,
TITLE_GENERATION_INSTRUCTION,
PLATFORM_SPECIFIC_GUIDELINES,
} from '../../utils/prompt/index.js';
import {
localizePromptObject,
extractLocaleFromRequest,
} from '../../services/localization/index.js';
import { sendSuccessResponseWithAttachments } from '../../utils/request/index.js';
import { enrichRequest } from '../../utils/requestEnrichment.js';

import { processAutomatischPR } from './PRAgent/index.js';
import { assemblePromptGraphAsync } from './promptAssemblyGraph.js';

// Import types
import type {
Expand Down Expand Up @@ -261,32 +260,28 @@ function validateRequest(requestBody: any, config: PromptConfig): string | null
* @returns Modified request data
*/
async function applyProfileDefaults(requestData: any, req: any, type: string): Promise<any> {
if (
type === 'social' &&
requestData.platforms?.includes('pressemitteilung') &&
!requestData.zitatgeber
) {
if (req?.user?.id) {
try {
const { getProfileService } = await import('../../services/user/index.js');
const profileService = getProfileService();
const profile = await profileService.getProfileById(req.user.id);

if (profile?.display_name) {
requestData.zitatgeber = profile.display_name;
console.log(
'[promptProcessor] Applied default zitatgeber from profile:',
profile.display_name
);
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.warn(
'[promptProcessor] Could not fetch profile for default zitatgeber:',
errorMessage
);
}
if (!req?.user?.id) return requestData;
try {
const { getProfileService } = await import('../../services/user/index.js');
const profileService = getProfileService();
const profile = await profileService.getProfileById(req.user.id);
if (!profile) return requestData;

if ((profile as any).custom_prompt?.trim()) {
requestData.customPrompt = (profile as any).custom_prompt;
}

if (
type === 'social' &&
requestData.platforms?.includes('pressemitteilung') &&
!requestData.zitatgeber &&
profile.display_name
) {
requestData.zitatgeber = profile.display_name;
}
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
console.warn('[promptProcessor] Could not fetch profile defaults:', msg);
}
return requestData;
}
Expand Down Expand Up @@ -662,9 +657,14 @@ export async function processGraphRequest(routeType: string, req: any, res: any)
return handleValidationError(res, `/${routeType}`, validationError);
}

// Apply profile defaults for optional fields (e.g., zitatgeber from display_name)
// Apply profile defaults for optional fields (e.g., customPrompt fallback, zitatgeber)
await applyProfileDefaults(requestData, req, routeType);

// Re-extract instructions after profile defaults may have set customPrompt
if (!extractedInstructions && requestData.customPrompt) {
extractedInstructions = requestData.customPrompt;
}

// Handle custom_generator special case
let generatorData: any = null;
if (config.features?.customPromptFromDb) {
Expand Down
5 changes: 1 addition & 4 deletions apps/api/database/postgres/local_setup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ CREATE TABLE IF NOT EXISTS profiles (
last_name TEXT,
display_name TEXT,
avatar_url TEXT,
custom_antrag_prompt TEXT,
custom_social_prompt TEXT,
deutschlandmodus BOOLEAN DEFAULT FALSE,
is_admin BOOLEAN DEFAULT FALSE,
profile_image INTEGER DEFAULT 1,
Expand All @@ -22,8 +20,7 @@ CREATE TABLE IF NOT EXISTS profiles (
username TEXT,
last_login TIMESTAMPTZ,
email TEXT,
custom_universal_prompt TEXT,
custom_gruenejugend_prompt TEXT,
custom_prompt TEXT,
igel_modus BOOLEAN DEFAULT FALSE,
beta_features JSONB DEFAULT '{}',
presseabbinder TEXT,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
-- ════════════════════════════════════════════════════════════════════════════
-- Migration: Merge per-generator Anweisungen into unified custom_prompt
-- ════════════════════════════════════════════════════════════════════════════
--
-- Context: The app previously had 6 separate prompt columns for different
-- generator types. These were replaced by a single `custom_prompt` column.
-- This migration merges any existing data from the old columns into
-- `custom_prompt` (if it is currently empty), then drops the old columns.
--
-- Safe to run multiple times: the DROP COLUMN uses IF EXISTS.
-- ════════════════════════════════════════════════════════════════════════════

BEGIN;

-- Step 1: Merge old per-type prompts into custom_prompt where it is empty
UPDATE profiles
SET custom_prompt = CONCAT_WS(
E'\n\n',
CASE WHEN NULLIF(TRIM(custom_antrag_prompt), '') IS NOT NULL
THEN '## Anträge' || E'\n' || TRIM(custom_antrag_prompt) END,
CASE WHEN NULLIF(TRIM(custom_social_prompt), '') IS NOT NULL
THEN '## Social Media' || E'\n' || TRIM(custom_social_prompt) END,
CASE WHEN NULLIF(TRIM(custom_rede_prompt), '') IS NOT NULL
THEN '## Reden' || E'\n' || TRIM(custom_rede_prompt) END,
CASE WHEN NULLIF(TRIM(custom_universal_prompt), '') IS NOT NULL
THEN '## Universell' || E'\n' || TRIM(custom_universal_prompt) END,
CASE WHEN NULLIF(TRIM(custom_gruenejugend_prompt), '') IS NOT NULL
THEN '## Grüne Jugend' || E'\n' || TRIM(custom_gruenejugend_prompt) END,
CASE WHEN NULLIF(TRIM(custom_buergeranfragen_prompt), '') IS NOT NULL
THEN '## Bürgeranfragen' || E'\n' || TRIM(custom_buergeranfragen_prompt) END
)
WHERE NULLIF(TRIM(COALESCE(custom_prompt, '')), '') IS NULL
AND (
NULLIF(TRIM(COALESCE(custom_antrag_prompt, '')), '') IS NOT NULL
OR NULLIF(TRIM(COALESCE(custom_social_prompt, '')), '') IS NOT NULL
OR NULLIF(TRIM(COALESCE(custom_rede_prompt, '')), '') IS NOT NULL
OR NULLIF(TRIM(COALESCE(custom_universal_prompt, '')), '') IS NOT NULL
OR NULLIF(TRIM(COALESCE(custom_gruenejugend_prompt, '')), '') IS NOT NULL
OR NULLIF(TRIM(COALESCE(custom_buergeranfragen_prompt, '')), '') IS NOT NULL
);

-- Step 2: Drop the old per-type prompt columns
ALTER TABLE profiles DROP COLUMN IF EXISTS custom_antrag_prompt;
ALTER TABLE profiles DROP COLUMN IF EXISTS custom_social_prompt;
ALTER TABLE profiles DROP COLUMN IF EXISTS custom_universal_prompt;
ALTER TABLE profiles DROP COLUMN IF EXISTS custom_gruenejugend_prompt;
ALTER TABLE profiles DROP COLUMN IF EXISTS custom_rede_prompt;
ALTER TABLE profiles DROP COLUMN IF EXISTS custom_buergeranfragen_prompt;

COMMIT;

-- Step 3: Verification query (run after migration)
-- Shows profiles whose custom_prompt was populated by the migration
SELECT id, display_name, LEFT(custom_prompt, 80) AS custom_prompt_preview
FROM profiles
WHERE custom_prompt IS NOT NULL AND custom_prompt != ''
ORDER BY updated_at DESC
LIMIT 20;
6 changes: 0 additions & 6 deletions apps/api/database/postgres/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ CREATE TABLE IF NOT EXISTS profiles (
last_name TEXT,
display_name TEXT,
avatar_url TEXT,
custom_antrag_prompt TEXT,
custom_social_prompt TEXT,
deutschlandmodus BOOLEAN DEFAULT FALSE,
is_admin BOOLEAN DEFAULT FALSE,
profile_image INTEGER DEFAULT 1,
Expand All @@ -58,10 +56,6 @@ CREATE TABLE IF NOT EXISTS profiles (
username TEXT,
last_login TIMESTAMPTZ,
email TEXT,
custom_universal_prompt TEXT,
custom_gruenejugend_prompt TEXT,
custom_rede_prompt TEXT,
custom_buergeranfragen_prompt TEXT,
custom_prompt TEXT,
igel_modus BOOLEAN DEFAULT FALSE,
beta_features JSONB DEFAULT '{}',
Expand Down
Loading
Loading