autoblogger 0.2.20 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +192 -2
- package/dist/index.d.mts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +291 -221
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +292 -222
- package/dist/index.mjs.map +1 -1
- package/dist/lib/markdown.d.mts +2 -2
- package/dist/lib/markdown.d.ts +2 -2
- package/dist/lib/markdown.js +1 -78
- package/dist/lib/markdown.js.map +1 -1
- package/dist/lib/markdown.mjs +2 -79
- package/dist/lib/markdown.mjs.map +1 -1
- package/dist/styles/autoblogger.css +1 -1
- package/dist/styles/preset.js +16 -0
- package/dist/styles/standalone.css +1 -1
- package/dist/ui.d.mts +30 -29
- package/dist/ui.d.ts +30 -29
- package/dist/ui.js +10090 -9608
- package/dist/ui.js.map +1 -1
- package/dist/ui.mjs +10098 -9614
- package/dist/ui.mjs.map +1 -1
- package/package.json +4 -1
package/dist/cli/index.js
CHANGED
|
@@ -446,6 +446,17 @@ async function promptInit(options) {
|
|
|
446
446
|
message: "Run database migration after setup?",
|
|
447
447
|
initial: true
|
|
448
448
|
});
|
|
449
|
+
questions.push({
|
|
450
|
+
type: "select",
|
|
451
|
+
name: "deploymentPlatform",
|
|
452
|
+
message: "Where will you deploy? (for RSS auto-draft scheduling)",
|
|
453
|
+
choices: [
|
|
454
|
+
{ title: "Vercel (serverless)", value: "vercel", description: "Creates API route + vercel.json cron" },
|
|
455
|
+
{ title: "Server (VPS/Docker)", value: "server", description: "Creates cron script for crontab" },
|
|
456
|
+
{ title: "Skip for now", value: "skip", description: "Set up auto-draft later" }
|
|
457
|
+
],
|
|
458
|
+
initial: 0
|
|
459
|
+
});
|
|
449
460
|
if (options.contentPaths.length > 0) {
|
|
450
461
|
const contentSummary = options.contentPaths.map((p) => `${p} (${options.contentCounts[p]} files)`).join(", ");
|
|
451
462
|
console.log(import_picocolors.default.cyan(`
|
|
@@ -478,7 +489,8 @@ Found existing content: ${contentSummary}`));
|
|
|
478
489
|
dbProvider: answers.dbProvider || "postgresql",
|
|
479
490
|
runMigration: answers.runMigration ?? true,
|
|
480
491
|
importContent: answers.importContent ?? false,
|
|
481
|
-
importPath: answers.importPath || options.contentPaths[0]
|
|
492
|
+
importPath: answers.importPath || options.contentPaths[0],
|
|
493
|
+
deploymentPlatform: answers.deploymentPlatform || "vercel"
|
|
482
494
|
};
|
|
483
495
|
}
|
|
484
496
|
async function confirm(message, initial = true) {
|
|
@@ -632,6 +644,121 @@ var WRITER_LAYOUT_TEMPLATE = `export default function WriterLayout({
|
|
|
632
644
|
}
|
|
633
645
|
`;
|
|
634
646
|
|
|
647
|
+
// src/cli/templates/auto-draft-script.ts
|
|
648
|
+
var AUTO_DRAFT_SCRIPT_TEMPLATE = `/**
|
|
649
|
+
* Auto-Draft Cron Script
|
|
650
|
+
*
|
|
651
|
+
* Fetches RSS feeds for active topic subscriptions and generates essay drafts.
|
|
652
|
+
* Run with: npx tsx --env-file=.env.local scripts/auto-draft.ts
|
|
653
|
+
*
|
|
654
|
+
* Schedule via cron:
|
|
655
|
+
* 0 6 * * * cd /path/to/project && npx tsx scripts/auto-draft.ts >> /var/log/auto-draft.log 2>&1
|
|
656
|
+
*/
|
|
657
|
+
|
|
658
|
+
import 'dotenv/config'
|
|
659
|
+
import { cms } from '../lib/cms'
|
|
660
|
+
|
|
661
|
+
async function main() {
|
|
662
|
+
const startTime = new Date()
|
|
663
|
+
console.log(\`[\${startTime.toISOString()}] Starting auto-draft...\`)
|
|
664
|
+
|
|
665
|
+
try {
|
|
666
|
+
const results = await cms.autoDraft.run()
|
|
667
|
+
|
|
668
|
+
if (results.length === 0) {
|
|
669
|
+
console.log(' No active topics to process.')
|
|
670
|
+
} else {
|
|
671
|
+
let totalGenerated = 0
|
|
672
|
+
let totalSkipped = 0
|
|
673
|
+
|
|
674
|
+
for (const r of results) {
|
|
675
|
+
console.log(\` \${r.topicName}: generated \${r.generated}, skipped \${r.skipped}\`)
|
|
676
|
+
totalGenerated += r.generated
|
|
677
|
+
totalSkipped += r.skipped
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
console.log(' ---')
|
|
681
|
+
console.log(\` Total: \${totalGenerated} essays generated, \${totalSkipped} articles skipped\`)
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const endTime = new Date()
|
|
685
|
+
const duration = (endTime.getTime() - startTime.getTime()) / 1000
|
|
686
|
+
console.log(\`[\${endTime.toISOString()}] Done in \${duration.toFixed(1)}s\`)
|
|
687
|
+
|
|
688
|
+
process.exit(0)
|
|
689
|
+
} catch (error) {
|
|
690
|
+
console.error('Auto-draft failed:', error)
|
|
691
|
+
process.exit(1)
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
main()
|
|
696
|
+
`;
|
|
697
|
+
|
|
698
|
+
// src/cli/templates/vercel-cron-route.ts
|
|
699
|
+
var VERCEL_CRON_ROUTE_TEMPLATE = `import { NextResponse } from 'next/server'
|
|
700
|
+
import { cms } from '@/lib/cms'
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Vercel Cron endpoint for RSS auto-draft generation.
|
|
704
|
+
*
|
|
705
|
+
* Triggered by Vercel Cron on schedule defined in vercel.json.
|
|
706
|
+
* Fetches RSS feeds for active topic subscriptions and generates essay drafts.
|
|
707
|
+
*
|
|
708
|
+
* To test manually:
|
|
709
|
+
* curl -H "Authorization: Bearer YOUR_CRON_SECRET" http://localhost:3000/api/cron/auto-draft
|
|
710
|
+
*/
|
|
711
|
+
export async function GET(request: Request) {
|
|
712
|
+
// Verify the request is from Vercel Cron (security)
|
|
713
|
+
const authHeader = request.headers.get('authorization')
|
|
714
|
+
if (authHeader !== \`Bearer \${process.env.CRON_SECRET}\`) {
|
|
715
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
const startTime = new Date()
|
|
719
|
+
console.log(\`[\${startTime.toISOString()}] Starting auto-draft via Vercel Cron...\`)
|
|
720
|
+
|
|
721
|
+
try {
|
|
722
|
+
const results = await cms.autoDraft.run()
|
|
723
|
+
|
|
724
|
+
if (results.length === 0) {
|
|
725
|
+
console.log(' No active topics to process.')
|
|
726
|
+
} else {
|
|
727
|
+
let totalGenerated = 0
|
|
728
|
+
let totalSkipped = 0
|
|
729
|
+
|
|
730
|
+
for (const r of results) {
|
|
731
|
+
console.log(\` \${r.topicName}: generated \${r.generated}, skipped \${r.skipped}\`)
|
|
732
|
+
totalGenerated += r.generated
|
|
733
|
+
totalSkipped += r.skipped
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
console.log(' ---')
|
|
737
|
+
console.log(\` Total: \${totalGenerated} essays generated, \${totalSkipped} articles skipped\`)
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const endTime = new Date()
|
|
741
|
+
const duration = (endTime.getTime() - startTime.getTime()) / 1000
|
|
742
|
+
console.log(\`[\${endTime.toISOString()}] Done in \${duration.toFixed(1)}s\`)
|
|
743
|
+
|
|
744
|
+
return NextResponse.json({
|
|
745
|
+
success: true,
|
|
746
|
+
results,
|
|
747
|
+
duration: \`\${duration.toFixed(1)}s\`,
|
|
748
|
+
})
|
|
749
|
+
} catch (error) {
|
|
750
|
+
console.error('Auto-draft failed:', error)
|
|
751
|
+
return NextResponse.json(
|
|
752
|
+
{ error: error instanceof Error ? error.message : 'Auto-draft failed' },
|
|
753
|
+
{ status: 500 }
|
|
754
|
+
)
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// Vercel Cron requires a longer timeout for AI generation
|
|
759
|
+
export const maxDuration = 300 // 5 minutes
|
|
760
|
+
`;
|
|
761
|
+
|
|
635
762
|
// src/cli/import.ts
|
|
636
763
|
var fs5 = __toESM(require("fs"));
|
|
637
764
|
var path5 = __toESM(require("path"));
|
|
@@ -895,11 +1022,15 @@ async function init(options = {}) {
|
|
|
895
1022
|
for (const contentPath of project.contentPaths) {
|
|
896
1023
|
contentCounts[contentPath] = countMarkdownFiles(path6.join(cwd, contentPath));
|
|
897
1024
|
}
|
|
1025
|
+
const hasVercelJson = fs6.existsSync(path6.join(cwd, "vercel.json"));
|
|
1026
|
+
const hasVercelDir = fs6.existsSync(path6.join(cwd, ".vercel"));
|
|
1027
|
+
const isLikelyVercel = hasVercelJson || hasVercelDir;
|
|
898
1028
|
let answers = {
|
|
899
1029
|
dbProvider: "postgresql",
|
|
900
1030
|
runMigration: !options.skipMigrate,
|
|
901
1031
|
importContent: !!options.importPath,
|
|
902
|
-
importPath: options.importPath || project.contentPaths[0]
|
|
1032
|
+
importPath: options.importPath || project.contentPaths[0],
|
|
1033
|
+
deploymentPlatform: isLikelyVercel ? "vercel" : "server"
|
|
903
1034
|
};
|
|
904
1035
|
if (!options.yes) {
|
|
905
1036
|
answers = await promptInit({
|
|
@@ -929,6 +1060,12 @@ Error: Found conflicting model names in your Prisma schema:`));
|
|
|
929
1060
|
console.log(` - ${project.appRouterPath}/api/cms/[...path]/route.ts`);
|
|
930
1061
|
console.log(` - ${project.appRouterPath}/(writer)/writer/[[...path]]/page.tsx`);
|
|
931
1062
|
console.log(` - ${project.appRouterPath}/(writer)/layout.tsx`);
|
|
1063
|
+
if (answers.deploymentPlatform === "vercel") {
|
|
1064
|
+
console.log(` - ${project.appRouterPath}/api/cron/auto-draft/route.ts (Vercel Cron endpoint)`);
|
|
1065
|
+
console.log(` - vercel.json (add cron schedule)`);
|
|
1066
|
+
} else if (answers.deploymentPlatform === "server") {
|
|
1067
|
+
console.log(` - scripts/auto-draft.ts (cron script for crontab)`);
|
|
1068
|
+
}
|
|
932
1069
|
console.log(` - globals.css (add CSS import)`);
|
|
933
1070
|
console.log(` - ${project.appRouterPath}/layout.tsx (add suppressHydrationWarning, GlobalShortcuts)`);
|
|
934
1071
|
if (answers.runMigration) {
|
|
@@ -999,6 +1136,53 @@ Would import ${count} posts from ${answers.importPath}`);
|
|
|
999
1136
|
fs6.writeFileSync(writerLayoutPath, WRITER_LAYOUT_TEMPLATE);
|
|
1000
1137
|
log("write", `Created ${project.appRouterPath}/(writer)/layout.tsx`);
|
|
1001
1138
|
}
|
|
1139
|
+
if (answers.deploymentPlatform === "vercel") {
|
|
1140
|
+
const cronRoutePath = path6.join(cwd, project.appRouterPath, "api", "cron", "auto-draft", "route.ts");
|
|
1141
|
+
if (fs6.existsSync(cronRoutePath)) {
|
|
1142
|
+
log("skip", `${project.appRouterPath}/api/cron/auto-draft/route.ts already exists`);
|
|
1143
|
+
} else {
|
|
1144
|
+
const cronRouteDir = path6.dirname(cronRoutePath);
|
|
1145
|
+
if (!fs6.existsSync(cronRouteDir)) {
|
|
1146
|
+
fs6.mkdirSync(cronRouteDir, { recursive: true });
|
|
1147
|
+
}
|
|
1148
|
+
fs6.writeFileSync(cronRoutePath, VERCEL_CRON_ROUTE_TEMPLATE);
|
|
1149
|
+
log("write", `Created ${project.appRouterPath}/api/cron/auto-draft/route.ts`);
|
|
1150
|
+
}
|
|
1151
|
+
const vercelJsonPath = path6.join(cwd, "vercel.json");
|
|
1152
|
+
let vercelConfig = {};
|
|
1153
|
+
if (fs6.existsSync(vercelJsonPath)) {
|
|
1154
|
+
try {
|
|
1155
|
+
vercelConfig = JSON.parse(fs6.readFileSync(vercelJsonPath, "utf-8"));
|
|
1156
|
+
} catch {
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
const cronPath = "/api/cron/auto-draft";
|
|
1160
|
+
const existingCron = vercelConfig.crons?.find((c) => c.path === cronPath);
|
|
1161
|
+
if (existingCron) {
|
|
1162
|
+
log("skip", "vercel.json already has auto-draft cron");
|
|
1163
|
+
} else {
|
|
1164
|
+
vercelConfig.crons = vercelConfig.crons || [];
|
|
1165
|
+
vercelConfig.crons.push({
|
|
1166
|
+
path: cronPath,
|
|
1167
|
+
schedule: "0 6 * * *"
|
|
1168
|
+
// Daily at 6am UTC
|
|
1169
|
+
});
|
|
1170
|
+
fs6.writeFileSync(vercelJsonPath, JSON.stringify(vercelConfig, null, 2) + "\n");
|
|
1171
|
+
log("write", "Updated vercel.json with auto-draft cron (daily at 6am UTC)");
|
|
1172
|
+
}
|
|
1173
|
+
} else if (answers.deploymentPlatform === "server") {
|
|
1174
|
+
const scriptsDir = path6.join(cwd, "scripts");
|
|
1175
|
+
const autoDraftScriptPath = path6.join(scriptsDir, "auto-draft.ts");
|
|
1176
|
+
if (fs6.existsSync(autoDraftScriptPath)) {
|
|
1177
|
+
log("skip", "scripts/auto-draft.ts already exists");
|
|
1178
|
+
} else {
|
|
1179
|
+
if (!fs6.existsSync(scriptsDir)) {
|
|
1180
|
+
fs6.mkdirSync(scriptsDir, { recursive: true });
|
|
1181
|
+
}
|
|
1182
|
+
fs6.writeFileSync(autoDraftScriptPath, AUTO_DRAFT_SCRIPT_TEMPLATE);
|
|
1183
|
+
log("write", "Created scripts/auto-draft.ts (schedule via crontab)");
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1002
1186
|
const globalsCssPath = findGlobalsCss(cwd);
|
|
1003
1187
|
if (globalsCssPath) {
|
|
1004
1188
|
const cssResult = patchGlobalsCss(globalsCssPath);
|
|
@@ -1095,6 +1279,12 @@ Would import ${count} posts from ${answers.importPath}`);
|
|
|
1095
1279
|
console.log(import_picocolors3.default.gray(" 1. Update lib/cms.ts with your auth configuration"));
|
|
1096
1280
|
console.log(import_picocolors3.default.gray(" 2. Add your auth check to app/(writer)/writer/[[...path]]/page.tsx"));
|
|
1097
1281
|
console.log(import_picocolors3.default.gray(" 3. Set ANTHROPIC_API_KEY and/or OPENAI_API_KEY for AI features"));
|
|
1282
|
+
if (answers.deploymentPlatform === "vercel") {
|
|
1283
|
+
console.log(import_picocolors3.default.gray(" 4. Set CRON_SECRET env var in Vercel for auto-draft security"));
|
|
1284
|
+
} else if (answers.deploymentPlatform === "server") {
|
|
1285
|
+
console.log(import_picocolors3.default.gray(" 4. Schedule scripts/auto-draft.ts via crontab:"));
|
|
1286
|
+
console.log(import_picocolors3.default.gray(" 0 6 * * * cd /path/to/project && npx tsx scripts/auto-draft.ts"));
|
|
1287
|
+
}
|
|
1098
1288
|
console.log("");
|
|
1099
1289
|
}
|
|
1100
1290
|
|
package/dist/index.d.mts
CHANGED
|
@@ -689,30 +689,35 @@ declare function buildAutoDraftPrompt(options: {
|
|
|
689
689
|
* Placeholders: {{RULES}}, {{STYLE_EXAMPLES}}, {{WORD_COUNT}}
|
|
690
690
|
*/
|
|
691
691
|
declare const DEFAULT_GENERATE_TEMPLATE = "<system>\n<role>Expert essay writer creating engaging, thoughtful content</role>\n\n<critical>\nALWAYS output a complete essay. NEVER respond conversationally.\n- Do NOT ask questions or request clarification\n- Do NOT say \"Here is your essay\" or similar preamble\n- Do NOT explain what you're going to write\n- If the prompt is vague, make creative choices and proceed\n- Output ONLY the essay in markdown format\n</critical>\n\n<rules>\n{{RULES}}\n</rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n\n<constraints>\n<word_count>{{WORD_COUNT}}</word_count>\n</constraints>\n\n<output_format>\nCRITICAL: Your response MUST start with exactly this format:\n\nLine 1: # [Your Title Here]\nLine 2: *[Your subtitle here]*\nLine 3: (blank line)\nLine 4+: Essay body in markdown\n\n<title_guidelines>\n- Be SPECIFIC, not generic (avoid \"The Power of\", \"Why X Matters\", \"A Guide to\")\n- Include a concrete detail, angle, or unexpected element\n- Create curiosity or make a bold claim\n- 5-12 words ideal\n</title_guidelines>\n\n<subtitle_guidelines>\n- One sentence that hooks the reader\n- Tease the main argument or reveal a key insight\n- Create tension, curiosity, or promise value\n- Make readers want to continue reading\n</subtitle_guidelines>\n</output_format>\n</system>";
|
|
692
|
+
|
|
692
693
|
/**
|
|
693
694
|
* Default template for chat interactions.
|
|
694
695
|
* Placeholders: {{CHAT_RULES}}, {{RULES}}, {{STYLE_EXAMPLES}}, {{ESSAY_CONTEXT}}
|
|
695
696
|
*/
|
|
696
697
|
declare const DEFAULT_CHAT_TEMPLATE = "<system>\n<role>Helpful writing assistant for essay creation and editing</role>\n\n<chat_rules>\n{{CHAT_RULES}}\n</chat_rules>\n\n<writing_rules>\n{{RULES}}\n</writing_rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n\n<context>\n{{ESSAY_CONTEXT}}\n</context>\n\n<behavior>\n- Be concise and actionable\n- When suggesting edits, be specific about what to change\n- Match the author's voice and style when writing\n- Ask clarifying questions if the request is ambiguous\n</behavior>\n</system>";
|
|
698
|
+
|
|
697
699
|
/**
|
|
698
700
|
* Default template for text rewriting.
|
|
699
701
|
* Placeholders: {{REWRITE_RULES}}, {{RULES}}, {{STYLE_EXAMPLES}}
|
|
700
702
|
*/
|
|
701
703
|
declare const DEFAULT_REWRITE_TEMPLATE = "<system>\n<role>Writing assistant that improves text quality</role>\n\n<rewrite_rules>\n{{REWRITE_RULES}}\n</rewrite_rules>\n\n<writing_rules>\n{{RULES}}\n</writing_rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n\n<behavior>\n- Preserve the original meaning exactly\n- Improve clarity, flow, and readability\n- Fix grammar and punctuation issues\n- Maintain the author's voice and tone\n- Output only the improved text, no explanations\n</behavior>\n</system>";
|
|
704
|
+
|
|
702
705
|
/**
|
|
703
706
|
* Default template for auto-drafting from news articles.
|
|
704
707
|
* Placeholders: {{AUTO_DRAFT_RULES}}, {{RULES}}, {{STYLE_EXAMPLES}}, {{TOPIC_NAME}}, {{ARTICLE_TITLE}}, {{ARTICLE_SUMMARY}}, {{ARTICLE_URL}}, {{AUTO_DRAFT_WORD_COUNT}}
|
|
705
708
|
*/
|
|
706
709
|
declare const DEFAULT_AUTO_DRAFT_TEMPLATE = "<system>\n<role>Expert essay writer creating engaging content from news articles</role>\n\n<auto_draft_rules>\n{{AUTO_DRAFT_RULES}}\n</auto_draft_rules>\n\n<writing_rules>\n{{RULES}}\n</writing_rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n\n<source_article>\n<topic>{{TOPIC_NAME}}</topic>\n<title>{{ARTICLE_TITLE}}</title>\n<summary>{{ARTICLE_SUMMARY}}</summary>\n<url>{{ARTICLE_URL}}</url>\n</source_article>\n\n<constraints>\n<word_count>{{AUTO_DRAFT_WORD_COUNT}}</word_count>\n</constraints>\n\n<output_format>\nCRITICAL: Your response MUST start with exactly this format:\n\nLine 1: # [Your Title Here]\nLine 2: *[Your subtitle here]*\nLine 3: (blank line)\nLine 4+: Essay body in markdown\n\n<title_guidelines>\n- Be SPECIFIC about the news angle, not generic\n- Include a concrete detail or unexpected element\n- Create curiosity or make a bold claim\n- 5-12 words ideal\n</title_guidelines>\n\n<subtitle_guidelines>\n- One sentence that hooks the reader\n- Tease the main argument or unique perspective\n- Create tension, curiosity, or promise value\n</subtitle_guidelines>\n</output_format>\n</system>";
|
|
710
|
+
|
|
707
711
|
/**
|
|
708
712
|
* Default template for essay outline generation.
|
|
709
713
|
* Placeholders: {{PLAN_RULES}}, {{STYLE_EXAMPLES}}
|
|
710
714
|
*/
|
|
711
|
-
declare const DEFAULT_PLAN_TEMPLATE = "<system>\n<role>
|
|
715
|
+
declare const DEFAULT_PLAN_TEMPLATE = "<system>\n<role>Essay outline generator - you ONLY output plans, never conversation</role>\n\n<critical>\nYOU ARE A PLAN GENERATOR. Every response must be a complete essay outline.\n\nABSOLUTE RULES:\n1. ALWAYS output a plan wrapped in <plan> tags\n2. NEVER have conversational responses outside the plan\n3. If user asks a question \u2192 answer by generating/revising a plan\n4. If user gives feedback \u2192 output the revised plan\n5. If user gives a topic \u2192 output a new plan for that topic\n6. Your ENTIRE response is ONLY the <plan>...</plan> block\n\nNO EXCEPTIONS. Every message you send is a plan.\n</critical>\n\n<rules>\n{{PLAN_RULES}}\n</rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n</system>";
|
|
712
716
|
/**
|
|
713
717
|
* Default rules for plan generation format.
|
|
714
718
|
*/
|
|
715
|
-
declare const DEFAULT_PLAN_RULES = "<format>\
|
|
719
|
+
declare const DEFAULT_PLAN_RULES = "<format>\nEXACT OUTPUT FORMAT - copy this structure precisely:\n\n<plan>\n# Essay Title\n*One-line subtitle*\n\n## Section Name\n- Key point\n\n## Section Name\n- Key point\n- Another point\n\n## Section Name\n- Key point\n</plan>\n</format>\n\n<syntax_requirements>\n- Title: \"# \" (hash + space) then title text\n- Subtitle: \"*\" + text + \"*\" (asterisks for italics)\n- Sections: \"## \" (double hash + space) then section name \n- Points: \"- \" (dash + space) then point text\n</syntax_requirements>\n\n<constraints>\n- 4-6 section headings (## lines)\n- 1-3 bullets per section \u2014 NEVER 4 or more\n- Bullets are short phrases, not full sentences\n- NO prose, NO paragraphs, NO explanations outside the plan\n- When revising, output the COMPLETE updated plan\n- NEVER output anything outside the <plan> tags\n</constraints>\n\n<title_guidelines>\n- Be SPECIFIC about the essay's angle\n- Include a concrete detail or unexpected element\n- Avoid generic patterns like \"The Power of\", \"Why X Matters\"\n- 5-12 words ideal\n</title_guidelines>\n\n<subtitle_guidelines>\n- One sentence that previews the main argument\n- Create curiosity or make a bold claim\n</subtitle_guidelines>";
|
|
720
|
+
|
|
716
721
|
/**
|
|
717
722
|
* Default template for expanding outlines into full essays.
|
|
718
723
|
* Placeholders: {{RULES}}, {{STYLE_EXAMPLES}}, {{PLAN}}
|
package/dist/index.d.ts
CHANGED
|
@@ -689,30 +689,35 @@ declare function buildAutoDraftPrompt(options: {
|
|
|
689
689
|
* Placeholders: {{RULES}}, {{STYLE_EXAMPLES}}, {{WORD_COUNT}}
|
|
690
690
|
*/
|
|
691
691
|
declare const DEFAULT_GENERATE_TEMPLATE = "<system>\n<role>Expert essay writer creating engaging, thoughtful content</role>\n\n<critical>\nALWAYS output a complete essay. NEVER respond conversationally.\n- Do NOT ask questions or request clarification\n- Do NOT say \"Here is your essay\" or similar preamble\n- Do NOT explain what you're going to write\n- If the prompt is vague, make creative choices and proceed\n- Output ONLY the essay in markdown format\n</critical>\n\n<rules>\n{{RULES}}\n</rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n\n<constraints>\n<word_count>{{WORD_COUNT}}</word_count>\n</constraints>\n\n<output_format>\nCRITICAL: Your response MUST start with exactly this format:\n\nLine 1: # [Your Title Here]\nLine 2: *[Your subtitle here]*\nLine 3: (blank line)\nLine 4+: Essay body in markdown\n\n<title_guidelines>\n- Be SPECIFIC, not generic (avoid \"The Power of\", \"Why X Matters\", \"A Guide to\")\n- Include a concrete detail, angle, or unexpected element\n- Create curiosity or make a bold claim\n- 5-12 words ideal\n</title_guidelines>\n\n<subtitle_guidelines>\n- One sentence that hooks the reader\n- Tease the main argument or reveal a key insight\n- Create tension, curiosity, or promise value\n- Make readers want to continue reading\n</subtitle_guidelines>\n</output_format>\n</system>";
|
|
692
|
+
|
|
692
693
|
/**
|
|
693
694
|
* Default template for chat interactions.
|
|
694
695
|
* Placeholders: {{CHAT_RULES}}, {{RULES}}, {{STYLE_EXAMPLES}}, {{ESSAY_CONTEXT}}
|
|
695
696
|
*/
|
|
696
697
|
declare const DEFAULT_CHAT_TEMPLATE = "<system>\n<role>Helpful writing assistant for essay creation and editing</role>\n\n<chat_rules>\n{{CHAT_RULES}}\n</chat_rules>\n\n<writing_rules>\n{{RULES}}\n</writing_rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n\n<context>\n{{ESSAY_CONTEXT}}\n</context>\n\n<behavior>\n- Be concise and actionable\n- When suggesting edits, be specific about what to change\n- Match the author's voice and style when writing\n- Ask clarifying questions if the request is ambiguous\n</behavior>\n</system>";
|
|
698
|
+
|
|
697
699
|
/**
|
|
698
700
|
* Default template for text rewriting.
|
|
699
701
|
* Placeholders: {{REWRITE_RULES}}, {{RULES}}, {{STYLE_EXAMPLES}}
|
|
700
702
|
*/
|
|
701
703
|
declare const DEFAULT_REWRITE_TEMPLATE = "<system>\n<role>Writing assistant that improves text quality</role>\n\n<rewrite_rules>\n{{REWRITE_RULES}}\n</rewrite_rules>\n\n<writing_rules>\n{{RULES}}\n</writing_rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n\n<behavior>\n- Preserve the original meaning exactly\n- Improve clarity, flow, and readability\n- Fix grammar and punctuation issues\n- Maintain the author's voice and tone\n- Output only the improved text, no explanations\n</behavior>\n</system>";
|
|
704
|
+
|
|
702
705
|
/**
|
|
703
706
|
* Default template for auto-drafting from news articles.
|
|
704
707
|
* Placeholders: {{AUTO_DRAFT_RULES}}, {{RULES}}, {{STYLE_EXAMPLES}}, {{TOPIC_NAME}}, {{ARTICLE_TITLE}}, {{ARTICLE_SUMMARY}}, {{ARTICLE_URL}}, {{AUTO_DRAFT_WORD_COUNT}}
|
|
705
708
|
*/
|
|
706
709
|
declare const DEFAULT_AUTO_DRAFT_TEMPLATE = "<system>\n<role>Expert essay writer creating engaging content from news articles</role>\n\n<auto_draft_rules>\n{{AUTO_DRAFT_RULES}}\n</auto_draft_rules>\n\n<writing_rules>\n{{RULES}}\n</writing_rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n\n<source_article>\n<topic>{{TOPIC_NAME}}</topic>\n<title>{{ARTICLE_TITLE}}</title>\n<summary>{{ARTICLE_SUMMARY}}</summary>\n<url>{{ARTICLE_URL}}</url>\n</source_article>\n\n<constraints>\n<word_count>{{AUTO_DRAFT_WORD_COUNT}}</word_count>\n</constraints>\n\n<output_format>\nCRITICAL: Your response MUST start with exactly this format:\n\nLine 1: # [Your Title Here]\nLine 2: *[Your subtitle here]*\nLine 3: (blank line)\nLine 4+: Essay body in markdown\n\n<title_guidelines>\n- Be SPECIFIC about the news angle, not generic\n- Include a concrete detail or unexpected element\n- Create curiosity or make a bold claim\n- 5-12 words ideal\n</title_guidelines>\n\n<subtitle_guidelines>\n- One sentence that hooks the reader\n- Tease the main argument or unique perspective\n- Create tension, curiosity, or promise value\n</subtitle_guidelines>\n</output_format>\n</system>";
|
|
710
|
+
|
|
707
711
|
/**
|
|
708
712
|
* Default template for essay outline generation.
|
|
709
713
|
* Placeholders: {{PLAN_RULES}}, {{STYLE_EXAMPLES}}
|
|
710
714
|
*/
|
|
711
|
-
declare const DEFAULT_PLAN_TEMPLATE = "<system>\n<role>
|
|
715
|
+
declare const DEFAULT_PLAN_TEMPLATE = "<system>\n<role>Essay outline generator - you ONLY output plans, never conversation</role>\n\n<critical>\nYOU ARE A PLAN GENERATOR. Every response must be a complete essay outline.\n\nABSOLUTE RULES:\n1. ALWAYS output a plan wrapped in <plan> tags\n2. NEVER have conversational responses outside the plan\n3. If user asks a question \u2192 answer by generating/revising a plan\n4. If user gives feedback \u2192 output the revised plan\n5. If user gives a topic \u2192 output a new plan for that topic\n6. Your ENTIRE response is ONLY the <plan>...</plan> block\n\nNO EXCEPTIONS. Every message you send is a plan.\n</critical>\n\n<rules>\n{{PLAN_RULES}}\n</rules>\n\n<style_reference>\n{{STYLE_EXAMPLES}}\n</style_reference>\n</system>";
|
|
712
716
|
/**
|
|
713
717
|
* Default rules for plan generation format.
|
|
714
718
|
*/
|
|
715
|
-
declare const DEFAULT_PLAN_RULES = "<format>\
|
|
719
|
+
declare const DEFAULT_PLAN_RULES = "<format>\nEXACT OUTPUT FORMAT - copy this structure precisely:\n\n<plan>\n# Essay Title\n*One-line subtitle*\n\n## Section Name\n- Key point\n\n## Section Name\n- Key point\n- Another point\n\n## Section Name\n- Key point\n</plan>\n</format>\n\n<syntax_requirements>\n- Title: \"# \" (hash + space) then title text\n- Subtitle: \"*\" + text + \"*\" (asterisks for italics)\n- Sections: \"## \" (double hash + space) then section name \n- Points: \"- \" (dash + space) then point text\n</syntax_requirements>\n\n<constraints>\n- 4-6 section headings (## lines)\n- 1-3 bullets per section \u2014 NEVER 4 or more\n- Bullets are short phrases, not full sentences\n- NO prose, NO paragraphs, NO explanations outside the plan\n- When revising, output the COMPLETE updated plan\n- NEVER output anything outside the <plan> tags\n</constraints>\n\n<title_guidelines>\n- Be SPECIFIC about the essay's angle\n- Include a concrete detail or unexpected element\n- Avoid generic patterns like \"The Power of\", \"Why X Matters\"\n- 5-12 words ideal\n</title_guidelines>\n\n<subtitle_guidelines>\n- One sentence that previews the main argument\n- Create curiosity or make a bold claim\n</subtitle_guidelines>";
|
|
720
|
+
|
|
716
721
|
/**
|
|
717
722
|
* Default template for expanding outlines into full essays.
|
|
718
723
|
* Placeholders: {{RULES}}, {{STYLE_EXAMPLES}}, {{PLAN}}
|