149 lines
4.2 KiB
JavaScript
149 lines
4.2 KiB
JavaScript
import { router } from '../../appRouter';
|
|
|
|
/**
|
|
* Resolves the active frontend route (path + search query).
|
|
* Falls back to window.location if router is not directly accessible.
|
|
* @returns {string} e.g. "/artikel" or "/artikel/ART-10042" or "/artikel?target=kabel"
|
|
*/
|
|
export function getCurrentRoute() {
|
|
if (typeof window !== 'undefined' && window.location) {
|
|
const { pathname = '/', search = '' } = window.location;
|
|
return `${pathname}${search}`;
|
|
}
|
|
return '/artikel';
|
|
}
|
|
|
|
/**
|
|
* Builds the <USERENV><ROUTE>...</ROUTE></USERENV> XML prefix for LLM agent prompts.
|
|
* @param {string} [route]
|
|
* @returns {string}
|
|
*/
|
|
export function buildUserEnvPrefix(route) {
|
|
const resolvedRoute = route || getCurrentRoute();
|
|
return `<USERENV><ROUTE>${resolvedRoute}</ROUTE></USERENV>`;
|
|
}
|
|
|
|
export const USER_ENV_REGEX = /<USERENV>[\s\S]*?(?:<\/USERENV>|$)\s*/gi;
|
|
|
|
/**
|
|
* Strips <USERENV>...</USERENV> tags from a message so it is not rendered in the chat view.
|
|
* @param {string} text
|
|
* @returns {string}
|
|
*/
|
|
export function stripUserEnv(text) {
|
|
if (typeof text !== 'string' || !text.includes('<USERENV')) {
|
|
return text || '';
|
|
}
|
|
return text.replace(USER_ENV_REGEX, '').trim();
|
|
}
|
|
|
|
/**
|
|
* Prepends the <USERENV><ROUTE>...</ROUTE></USERENV> block to the user prompt if not already present.
|
|
* @param {string} text
|
|
* @param {string} [route]
|
|
* @returns {string}
|
|
*/
|
|
export function attachUserEnv(text = '', route) {
|
|
const trimmed = typeof text === 'string' ? text.trim() : '';
|
|
if (trimmed.includes('<USERENV')) {
|
|
return trimmed;
|
|
}
|
|
const prefix = buildUserEnvPrefix(route);
|
|
return trimmed ? `${prefix}\n\n${trimmed}` : prefix;
|
|
}
|
|
|
|
/**
|
|
* Checks if a tool name is the set-user-route tool.
|
|
* @param {string} name
|
|
* @returns {boolean}
|
|
*/
|
|
export function isSetUserRouteTool(name) {
|
|
if (!name || typeof name !== 'string') return false;
|
|
const n = name.trim().toLowerCase();
|
|
return n === 'set-user-route' || n === 'set_user_route';
|
|
}
|
|
|
|
/**
|
|
* Extracts the target route string from tool data arguments/parameters/result/content.
|
|
* @param {object} data
|
|
* @returns {string|null}
|
|
*/
|
|
export function extractRouteFromToolData(data) {
|
|
if (!data) return null;
|
|
// 1. From result
|
|
if (data.result) {
|
|
if (typeof data.result === 'object' && data.result.route) {
|
|
return String(data.result.route);
|
|
}
|
|
if (typeof data.result === 'string') {
|
|
try {
|
|
const parsed = JSON.parse(data.result);
|
|
if (parsed?.route) return String(parsed.route);
|
|
} catch {}
|
|
}
|
|
}
|
|
// 2. From arguments or parameters
|
|
const args = data.arguments || data.parameters;
|
|
if (args) {
|
|
if (typeof args === 'object' && args.route) {
|
|
return String(args.route);
|
|
}
|
|
if (typeof args === 'string') {
|
|
try {
|
|
const parsed = JSON.parse(args);
|
|
if (parsed?.route) return String(parsed.route);
|
|
} catch {}
|
|
}
|
|
}
|
|
// 3. From content
|
|
if (data.content) {
|
|
if (typeof data.content === 'object' && data.content.route) {
|
|
return String(data.content.route);
|
|
}
|
|
if (typeof data.content === 'string') {
|
|
try {
|
|
const parsed = JSON.parse(data.content);
|
|
if (parsed?.route) return String(parsed.route);
|
|
} catch {}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
const navigatedToolCallIds = new Set();
|
|
|
|
/**
|
|
* Navigates the application to the given client route.
|
|
* @param {string} route
|
|
* @param {string} [toolCallId]
|
|
*/
|
|
export async function navigateToClientRoute(route, toolCallId) {
|
|
if (!route || typeof route !== 'string') return;
|
|
const target = route.trim();
|
|
if (!target) return;
|
|
|
|
if (toolCallId) {
|
|
if (navigatedToolCallIds.has(toolCallId)) return;
|
|
navigatedToolCallIds.add(toolCallId);
|
|
}
|
|
|
|
try {
|
|
if (router?.navigate) {
|
|
const current = router.state?.location
|
|
? `${router.state.location.pathname}${router.state.location.search || ''}`
|
|
: (typeof window !== 'undefined' ? `${window.location.pathname}${window.location.search || ''}` : '');
|
|
if (current !== target) {
|
|
void router.navigate(target);
|
|
}
|
|
return;
|
|
}
|
|
} catch (err) {
|
|
console.warn('[userEnv] Router navigation failed:', err);
|
|
}
|
|
|
|
if (typeof window !== 'undefined' && window.location) {
|
|
window.location.href = target;
|
|
}
|
|
}
|
|
|