Page Builder ships: labelled-section AI output parsed deterministically, escaped renderer, one page per position at public /p/<id> with angle video + QR, rebuild keeps the same URL; L2 tile live
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+22
-6
@@ -68,10 +68,14 @@ function buildMessages(kind, brief, member) {
|
||||
|
||||
// Engine call. Long timeout: the agent narrates internally before answering.
|
||||
function generate(kind, brief, member) {
|
||||
return call(buildMessages(kind, brief, member)).then(function (t) { return cleanup(t, member); });
|
||||
}
|
||||
|
||||
function call(messages) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const c = creds();
|
||||
if (!c) return reject(new Error('The Copy Engine is not configured yet.'));
|
||||
const body = JSON.stringify({ model: c.model || 'hermes-agent', messages: buildMessages(kind, brief, member) });
|
||||
if (!c) return reject(new Error('The engine is not configured yet.'));
|
||||
const body = JSON.stringify({ model: c.model || 'hermes-agent', messages: messages });
|
||||
const u = new URL(c.url.replace(/\/$/, '') + '/chat/completions');
|
||||
const lib = u.protocol === 'https:' ? require('https') : require('http');
|
||||
const req = lib.request({
|
||||
@@ -84,14 +88,13 @@ function generate(kind, brief, member) {
|
||||
if (res.statusCode !== 200) return reject(new Error('Engine returned ' + res.statusCode));
|
||||
try {
|
||||
const j = JSON.parse(data);
|
||||
let text = (j.choices && j.choices[0] && j.choices[0].message && j.choices[0].message.content || '').trim();
|
||||
text = cleanup(text, member);
|
||||
const text = (j.choices && j.choices[0] && j.choices[0].message && j.choices[0].message.content || '').trim();
|
||||
if (!text) return reject(new Error('The engine came back empty — try again.'));
|
||||
resolve(text);
|
||||
} catch (e) { reject(new Error('Could not read the engine response.')); }
|
||||
});
|
||||
});
|
||||
req.on('error', function (e) { reject(new Error('Could not reach the Copy Engine: ' + e.message)); });
|
||||
req.on('error', function (e) { reject(new Error('Could not reach the engine: ' + e.message)); });
|
||||
req.setTimeout(240000, function () { req.destroy(new Error('The engine took too long — try again.')); });
|
||||
req.write(body); req.end();
|
||||
});
|
||||
@@ -114,4 +117,17 @@ function cleanup(text, member) {
|
||||
return t.trim();
|
||||
}
|
||||
|
||||
module.exports = { init, configured, generate, KINDS };
|
||||
// Raw generation for tools that supply their own instruction (Page Builder).
|
||||
// Still carries the facts + compliance + voice; only FORMAT is the caller's.
|
||||
function generateRaw(instruction) {
|
||||
return call([
|
||||
{ role: 'system', content:
|
||||
'You write for a member of the RM Circle team.\n\nWHAT IT IS: ' + FACTS +
|
||||
'\n\nVOICE: ' + VOICE +
|
||||
'\n\nCOMPLIANCE (absolute): ' + COMPLIANCE +
|
||||
'\n\nFollow the requested output format EXACTLY. No preamble, no explanation, no markdown fences.' },
|
||||
{ role: 'user', content: instruction }
|
||||
]);
|
||||
}
|
||||
|
||||
module.exports = { init, configured, generate, generateRaw, KINDS };
|
||||
|
||||
Reference in New Issue
Block a user