enh: support commands in note chat

This commit is contained in:
Timothy Jaeryang Baek
2025-07-09 01:49:43 +04:00
parent e9821c0881
commit 9632f40335
3 changed files with 375 additions and 134 deletions

View File

@@ -31,6 +31,7 @@
compressImage,
createMessagesList,
extractCurlyBraceWords,
extractInputVariables,
getCurrentDateTime,
getFormattedDate,
getFormattedTime,
@@ -118,124 +119,6 @@
codeInterpreterEnabled
});
const extractInputVariables = (text: string): Record<string, any> => {
const regex = /{{\s*([^|}\s]+)\s*\|\s*([^}]+)\s*}}/g;
const regularRegex = /{{\s*([^|}\s]+)\s*}}/g;
const variables: Record<string, any> = {};
let match;
// Use exec() loop instead of matchAll() for better compatibility
while ((match = regex.exec(text)) !== null) {
const varName = match[1].trim();
const definition = match[2].trim();
variables[varName] = parseVariableDefinition(definition);
}
// Then, extract regular variables (without pipe) - only if not already processed
while ((match = regularRegex.exec(text)) !== null) {
const varName = match[1].trim();
// Only add if not already processed as custom variable
if (!variables.hasOwnProperty(varName)) {
variables[varName] = { type: 'text' }; // Default type for regular variables
}
}
return variables;
};
const splitProperties = (str: string, delimiter: string): string[] => {
const result: string[] = [];
let current = '';
let depth = 0;
let inString = false;
let escapeNext = false;
for (let i = 0; i < str.length; i++) {
const char = str[i];
if (escapeNext) {
current += char;
escapeNext = false;
continue;
}
if (char === '\\') {
current += char;
escapeNext = true;
continue;
}
if (char === '"' && !escapeNext) {
inString = !inString;
current += char;
continue;
}
if (!inString) {
if (char === '{' || char === '[') {
depth++;
} else if (char === '}' || char === ']') {
depth--;
}
if (char === delimiter && depth === 0) {
result.push(current.trim());
current = '';
continue;
}
}
current += char;
}
if (current.trim()) {
result.push(current.trim());
}
return result;
};
const parseVariableDefinition = (definition: string): Record<string, any> => {
// Use splitProperties for the main colon delimiter to handle quoted strings
const parts = splitProperties(definition, ':');
const [firstPart, ...propertyParts] = parts;
// Parse type (explicit or implied)
const type = firstPart.startsWith('type=') ? firstPart.slice(5) : firstPart;
// Parse properties using reduce
const properties = propertyParts.reduce((props, part) => {
// Use splitProperties for the equals sign as well, in case there are nested quotes
const equalsParts = splitProperties(part, '=');
const [propertyName, ...valueParts] = equalsParts;
const propertyValue = valueParts.join('='); // Handle values with = signs
return propertyName && propertyValue
? {
...props,
[propertyName.trim()]: parseJsonValue(propertyValue.trim())
}
: props;
}, {});
return { type, ...properties };
};
const parseJsonValue = (value: string): any => {
// Remove surrounding quotes if present (for string values)
if (value.startsWith('"') && value.endsWith('"')) {
return value.slice(1, -1);
}
// Check if it starts with square or curly brackets (JSON)
if (/^[\[{]/.test(value)) {
try {
return JSON.parse(value);
} catch {
return value; // Return as string if JSON parsing fails
}
}
return value;
};
const inputVariableHandler = async (text: string) => {
inputVariables = extractInputVariables(text);
if (Object.keys(inputVariables).length > 0) {