VinOS Agent commited on
Commit
b11a2d7
·
1 Parent(s): c62723a

SEO Engine V4: Parametric Advanced Writing constraints (POV, Intent, Tone, Size)

Browse files
Files changed (3) hide show
  1. database/local_db.json +6 -0
  2. server.js +32 -24
  3. skills/seo_writer.js +4 -1
database/local_db.json CHANGED
@@ -25,6 +25,12 @@
25
  "active_experiments": 0
26
  },
27
  "telegram_log": [
 
 
 
 
 
 
28
  {
29
  "direction": "OUT",
30
  "chatId": "8743583463",
 
25
  "active_experiments": 0
26
  },
27
  "telegram_log": [
28
+ {
29
+ "direction": "OUT",
30
+ "chatId": "8743583463",
31
+ "text": "<b>VinOS Daily Check-in</b>\nHow is the Token Gashapon project coming along? Ready for the next arbitrage move?",
32
+ "ts": "2026-03-21T19:17:10.784Z"
33
+ },
34
  {
35
  "direction": "OUT",
36
  "chatId": "8743583463",
server.js CHANGED
@@ -392,36 +392,44 @@ app.post('/api/telegram-webhook', async (req, res) => {
392
  }
393
  }
394
  } else if (userText.toLowerCase().startsWith('/write')) {
395
- const parts = userText.split(' ');
 
396
 
397
- let targetSiteId = null;
398
- let size = 'medium';
399
- let topicIndex = 1;
400
 
401
  let sites = {};
402
  try { sites = JSON.parse(process.env.WP_SITES_JSON || "{}"); } catch(e){}
403
  const siteKeys = Object.keys(sites);
404
-
405
- if (siteKeys.includes(parts[1])) {
406
- targetSiteId = parts[1];
407
- topicIndex++;
408
- }
409
-
410
- const possibleSize = parts[topicIndex]?.toLowerCase();
411
- if (['short', 'medium', 'dense'].includes(possibleSize)) {
412
- size = possibleSize;
413
- topicIndex++;
414
- }
415
-
416
- const topic = parts.slice(topicIndex).join(' ');
417
-
418
- if (!topic) {
419
- const siteList = siteKeys.length > 0 ? `\n\n🏢 <b>Available Sites:</b> ${siteKeys.join(', ')}` : '\n\n⚠️ No sites configured in WP_SITES_JSON.';
420
- await apiCaller.sendTelegramMessage(chatId, `❌ Usage: /write [siteName] [short|medium|dense] [topic]${siteList}`);
421
  } else {
422
- const siteLabel = targetSiteId ? `[Site: ${targetSiteId}]` : '[Default Site]';
423
- await apiCaller.sendTelegramMessage(chatId, `📝 <b>SEO Engine:</b> Architecting 100% Unique [${size.toUpperCase()}] Article on "${topic}" with Dynamic Images...`);
424
- const articleRes = await seoWriter.generateArticle(size, topic);
 
 
 
 
 
 
 
 
 
 
 
425
  if (articleRes.success) {
426
  await apiCaller.sendTelegramMessage(chatId, `✅ <b>Article Generated!</b> Scoring EEAT...`);
427
  const scoreRes = await seoWriter.scoreEEAT(articleRes.html);
 
392
  }
393
  }
394
  } else if (userText.toLowerCase().startsWith('/write')) {
395
+ // Parse arguments smartly handling quotes: /write site "Topic" size "POV" "Intent" "Tone"
396
+ const args = userText.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || [];
397
 
398
+ // Remove quotes from matched strings
399
+ const cleanArgs = args.map(arg => arg.replace(/^["'](.*)["']$/, '$1'));
 
400
 
401
  let sites = {};
402
  try { sites = JSON.parse(process.env.WP_SITES_JSON || "{}"); } catch(e){}
403
  const siteKeys = Object.keys(sites);
404
+ const defaultSite = siteKeys.length > 0 ? siteKeys[0] : 'None';
405
+
406
+ if (cleanArgs.length < 7) {
407
+ const helpMsg = `⚠️ <b>Missing Parameters for /write</b>\n\n` +
408
+ `To architect an elite SEO article, I need instructions. Please use quotes for multi-word parameters.\n\n` +
409
+ `<b>Structure:</b>\n` +
410
+ `/write [SiteID] "[Topic]" [Size] "[POV]" "[Intent]" "[Tone]"\n\n` +
411
+ `<b>Available Site IDs:</b> ${siteKeys.join(', ') || 'Configure WP_SITES_JSON'}\n` +
412
+ `<b>Sizes:</b> short, medium, dense\n` +
413
+ `<b>POV:</b> "1st person singular", "1st person plural", "2nd person", "3rd person"\n\n` +
414
+ `<b>Example:</b>\n` +
415
+ `/write ${defaultSite} "Agentic Workflow" medium "1st person plural" "Educational" "Authoritative"`;
416
+
417
+ await apiCaller.sendTelegramMessage(chatId, helpMsg);
 
 
 
418
  } else {
419
+ const targetSiteId = cleanArgs[1];
420
+ const topic = cleanArgs[2];
421
+ const size = cleanArgs[3].toLowerCase();
422
+ const pov = cleanArgs[4];
423
+ const intent = cleanArgs[5];
424
+ const tone = cleanArgs[6];
425
+
426
+ if (!siteKeys.includes(targetSiteId)) {
427
+ await apiCaller.sendTelegramMessage(chatId, `❌ Unknown Site ID: ${targetSiteId}\nAvailable: ${siteKeys.join(', ')}`);
428
+ return;
429
+ }
430
+
431
+ await apiCaller.sendTelegramMessage(chatId, `📝 <b>SEO Engine:</b> Architecting 100% Unique [${size.toUpperCase()}] Article on "${topic}"...\n<b>Tone:</b> ${tone}\n<b>POV:</b> ${pov}`);
432
+ const articleRes = await seoWriter.generateArticle(size, pov, intent, tone, topic);
433
  if (articleRes.success) {
434
  await apiCaller.sendTelegramMessage(chatId, `✅ <b>Article Generated!</b> Scoring EEAT...`);
435
  const scoreRes = await seoWriter.scoreEEAT(articleRes.html);
skills/seo_writer.js CHANGED
@@ -9,7 +9,7 @@ class SeoWriter {
9
  /**
10
  * Generates a complete SEO article including Meta tags and JSON-LD schema.
11
  */
12
- async generateArticle(size, topic) {
13
  console.log(`[SEO Writer] Architecting ${size} article on: ${topic}`);
14
 
15
  let words = "1500 - 2500";
@@ -23,6 +23,9 @@ Write a comprehensive, EEAT-compliant article about: "${topic}"
23
  PARAMETERS:
24
  - Length: ${words} words.
25
  - Images: Minimum of ${minImages} images.
 
 
 
26
 
27
  CRITICAL RULES:
28
  1. STRICT HTML ONLY: You MUST format the output entirely in HTML. Use <strong>, <em>, <h2>, <h3>, <ul>, <p>. YOU ARE FORBIDDEN FROM USING MARKDOWN ASTERISKS (**bold**).
 
9
  /**
10
  * Generates a complete SEO article including Meta tags and JSON-LD schema.
11
  */
12
+ async generateArticle(size, pov, intent, tone, topic) {
13
  console.log(`[SEO Writer] Architecting ${size} article on: ${topic}`);
14
 
15
  let words = "1500 - 2500";
 
23
  PARAMETERS:
24
  - Length: ${words} words.
25
  - Images: Minimum of ${minImages} images.
26
+ - Point of View (POV): ${pov}
27
+ - Search Intent: ${intent}
28
+ - Tone of Voice: ${tone}
29
 
30
  CRITICAL RULES:
31
  1. STRICT HTML ONLY: You MUST format the output entirely in HTML. Use <strong>, <em>, <h2>, <h3>, <ul>, <p>. YOU ARE FORBIDDEN FROM USING MARKDOWN ASTERISKS (**bold**).