autoblogger 0.2.21 → 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/index.js CHANGED
@@ -3481,10 +3481,17 @@ var init_dist2 = __esm({
3481
3481
  }
3482
3482
  });
3483
3483
 
3484
- // src/ai/prompts.ts
3485
- var DEFAULT_GENERATE_TEMPLATE, DEFAULT_CHAT_TEMPLATE, DEFAULT_REWRITE_TEMPLATE, DEFAULT_AUTO_DRAFT_TEMPLATE, DEFAULT_PLAN_TEMPLATE, DEFAULT_PLAN_RULES, DEFAULT_AGENT_TEMPLATE, DEFAULT_EXPAND_PLAN_TEMPLATE, DEFAULT_SEARCH_ONLY_PROMPT;
3486
- var init_prompts = __esm({
3487
- "src/ai/prompts.ts"() {
3484
+ // src/ai/prompts/types.ts
3485
+ var init_types4 = __esm({
3486
+ "src/ai/prompts/types.ts"() {
3487
+ "use strict";
3488
+ }
3489
+ });
3490
+
3491
+ // src/ai/prompts/templates/generate.ts
3492
+ var DEFAULT_GENERATE_TEMPLATE;
3493
+ var init_generate = __esm({
3494
+ "src/ai/prompts/templates/generate.ts"() {
3488
3495
  "use strict";
3489
3496
  DEFAULT_GENERATE_TEMPLATE = `<system>
3490
3497
  <role>Expert essay writer creating engaging, thoughtful content</role>
@@ -3533,6 +3540,14 @@ Line 4+: Essay body in markdown
3533
3540
  </subtitle_guidelines>
3534
3541
  </output_format>
3535
3542
  </system>`;
3543
+ }
3544
+ });
3545
+
3546
+ // src/ai/prompts/templates/chat.ts
3547
+ var DEFAULT_CHAT_TEMPLATE;
3548
+ var init_chat = __esm({
3549
+ "src/ai/prompts/templates/chat.ts"() {
3550
+ "use strict";
3536
3551
  DEFAULT_CHAT_TEMPLATE = `<system>
3537
3552
  <role>Helpful writing assistant for essay creation and editing</role>
3538
3553
 
@@ -3559,6 +3574,14 @@ Line 4+: Essay body in markdown
3559
3574
  - Ask clarifying questions if the request is ambiguous
3560
3575
  </behavior>
3561
3576
  </system>`;
3577
+ }
3578
+ });
3579
+
3580
+ // src/ai/prompts/templates/rewrite.ts
3581
+ var DEFAULT_REWRITE_TEMPLATE;
3582
+ var init_rewrite = __esm({
3583
+ "src/ai/prompts/templates/rewrite.ts"() {
3584
+ "use strict";
3562
3585
  DEFAULT_REWRITE_TEMPLATE = `<system>
3563
3586
  <role>Writing assistant that improves text quality</role>
3564
3587
 
@@ -3582,6 +3605,14 @@ Line 4+: Essay body in markdown
3582
3605
  - Output only the improved text, no explanations
3583
3606
  </behavior>
3584
3607
  </system>`;
3608
+ }
3609
+ });
3610
+
3611
+ // src/ai/prompts/templates/auto-draft.ts
3612
+ var DEFAULT_AUTO_DRAFT_TEMPLATE;
3613
+ var init_auto_draft = __esm({
3614
+ "src/ai/prompts/templates/auto-draft.ts"() {
3615
+ "use strict";
3585
3616
  DEFAULT_AUTO_DRAFT_TEMPLATE = `<system>
3586
3617
  <role>Expert essay writer creating engaging content from news articles</role>
3587
3618
 
@@ -3630,11 +3661,29 @@ Line 4+: Essay body in markdown
3630
3661
  </subtitle_guidelines>
3631
3662
  </output_format>
3632
3663
  </system>`;
3664
+ }
3665
+ });
3666
+
3667
+ // src/ai/prompts/templates/plan.ts
3668
+ var DEFAULT_PLAN_TEMPLATE, DEFAULT_PLAN_RULES;
3669
+ var init_plan = __esm({
3670
+ "src/ai/prompts/templates/plan.ts"() {
3671
+ "use strict";
3633
3672
  DEFAULT_PLAN_TEMPLATE = `<system>
3634
- <role>Writing assistant that creates essay outlines</role>
3673
+ <role>Essay outline generator - you ONLY output plans, never conversation</role>
3635
3674
 
3636
3675
  <critical>
3637
- Wrap your ENTIRE response in <plan> tags. Output NOTHING outside the tags.
3676
+ YOU ARE A PLAN GENERATOR. Every response must be a complete essay outline.
3677
+
3678
+ ABSOLUTE RULES:
3679
+ 1. ALWAYS output a plan wrapped in <plan> tags
3680
+ 2. NEVER have conversational responses outside the plan
3681
+ 3. If user asks a question \u2192 answer by generating/revising a plan
3682
+ 4. If user gives feedback \u2192 output the revised plan
3683
+ 5. If user gives a topic \u2192 output a new plan for that topic
3684
+ 6. Your ENTIRE response is ONLY the <plan>...</plan> block
3685
+
3686
+ NO EXCEPTIONS. Every message you send is a plan.
3638
3687
  </critical>
3639
3688
 
3640
3689
  <rules>
@@ -3646,7 +3695,7 @@ Wrap your ENTIRE response in <plan> tags. Output NOTHING outside the tags.
3646
3695
  </style_reference>
3647
3696
  </system>`;
3648
3697
  DEFAULT_PLAN_RULES = `<format>
3649
- STRICT LIMIT: Maximum 3 bullets per section. Most sections should have 1-2 bullets.
3698
+ EXACT OUTPUT FORMAT - copy this structure precisely:
3650
3699
 
3651
3700
  <plan>
3652
3701
  # Essay Title
@@ -3664,12 +3713,20 @@ STRICT LIMIT: Maximum 3 bullets per section. Most sections should have 1-2 bulle
3664
3713
  </plan>
3665
3714
  </format>
3666
3715
 
3716
+ <syntax_requirements>
3717
+ - Title: "# " (hash + space) then title text
3718
+ - Subtitle: "*" + text + "*" (asterisks for italics)
3719
+ - Sections: "## " (double hash + space) then section name
3720
+ - Points: "- " (dash + space) then point text
3721
+ </syntax_requirements>
3722
+
3667
3723
  <constraints>
3668
3724
  - 4-6 section headings (## lines)
3669
3725
  - 1-3 bullets per section \u2014 NEVER 4 or more
3670
- - Bullets are short phrases, not sentences
3671
- - No prose, no paragraphs, no explanations
3672
- - When revising, output the complete updated plan
3726
+ - Bullets are short phrases, not full sentences
3727
+ - NO prose, NO paragraphs, NO explanations outside the plan
3728
+ - When revising, output the COMPLETE updated plan
3729
+ - NEVER output anything outside the <plan> tags
3673
3730
  </constraints>
3674
3731
 
3675
3732
  <title_guidelines>
@@ -3683,6 +3740,14 @@ STRICT LIMIT: Maximum 3 bullets per section. Most sections should have 1-2 bulle
3683
3740
  - One sentence that previews the main argument
3684
3741
  - Create curiosity or make a bold claim
3685
3742
  </subtitle_guidelines>`;
3743
+ }
3744
+ });
3745
+
3746
+ // src/ai/prompts/templates/agent.ts
3747
+ var DEFAULT_AGENT_TEMPLATE;
3748
+ var init_agent = __esm({
3749
+ "src/ai/prompts/templates/agent.ts"() {
3750
+ "use strict";
3686
3751
  DEFAULT_AGENT_TEMPLATE = `<agent_mode>
3687
3752
  CRITICAL: You are in AGENT MODE. You MUST make edits to the essay using edit commands.
3688
3753
 
@@ -3719,6 +3784,40 @@ RULES:
3719
3784
  - Keep explanatory text minimal - focus on the edits
3720
3785
  - Edits are applied automatically when you output the :::edit blocks
3721
3786
  </agent_mode>`;
3787
+ }
3788
+ });
3789
+
3790
+ // src/ai/prompts/templates/ask.ts
3791
+ var DEFAULT_ASK_TEMPLATE;
3792
+ var init_ask = __esm({
3793
+ "src/ai/prompts/templates/ask.ts"() {
3794
+ "use strict";
3795
+ DEFAULT_ASK_TEMPLATE = `<ask_mode>
3796
+ You are in ASK MODE. You can write, discuss, and create content freely in your responses.
3797
+
3798
+ The ONLY restriction: you cannot push changes directly to the editor document.
3799
+
3800
+ PROHIBITED (these modify the document):
3801
+ - :::edit blocks
3802
+ - JSON with "type": "replace_all", "replace_section", "insert", or "delete"
3803
+
3804
+ ALLOWED (do these freely):
3805
+ - Write full essays, articles, drafts in your response
3806
+ - Use markdown formatting (headers, bold, lists, etc.)
3807
+ - Answer questions, give feedback, brainstorm ideas
3808
+ - Create any content the user asks for
3809
+
3810
+ When you write content in Ask mode, it stays in the chat. The user can copy it if they want.
3811
+ If the user wants content inserted directly into their document, tell them to switch to Agent mode.
3812
+ </ask_mode>`;
3813
+ }
3814
+ });
3815
+
3816
+ // src/ai/prompts/templates/expand-plan.ts
3817
+ var DEFAULT_EXPAND_PLAN_TEMPLATE;
3818
+ var init_expand_plan = __esm({
3819
+ "src/ai/prompts/templates/expand-plan.ts"() {
3820
+ "use strict";
3722
3821
  DEFAULT_EXPAND_PLAN_TEMPLATE = `<system>
3723
3822
  <role>Writing assistant that expands essay outlines into full drafts</role>
3724
3823
 
@@ -3757,6 +3856,14 @@ If the plan title is generic, improve it to be:
3757
3856
  </title_refinement>
3758
3857
  </output_format>
3759
3858
  </system>`;
3859
+ }
3860
+ });
3861
+
3862
+ // src/ai/prompts/templates/search.ts
3863
+ var DEFAULT_SEARCH_ONLY_PROMPT;
3864
+ var init_search = __esm({
3865
+ "src/ai/prompts/templates/search.ts"() {
3866
+ "use strict";
3760
3867
  DEFAULT_SEARCH_ONLY_PROMPT = `You are a research assistant helping a writer gather facts and information.
3761
3868
 
3762
3869
  Your task is to provide accurate, well-sourced information to help with essay writing.
@@ -3772,6 +3879,38 @@ Do NOT write the essay - just provide research findings.`;
3772
3879
  }
3773
3880
  });
3774
3881
 
3882
+ // src/ai/prompts/builders.ts
3883
+ var init_builders = __esm({
3884
+ "src/ai/prompts/builders.ts"() {
3885
+ "use strict";
3886
+ init_generate();
3887
+ init_chat();
3888
+ init_rewrite();
3889
+ init_plan();
3890
+ init_agent();
3891
+ init_expand_plan();
3892
+ init_search();
3893
+ }
3894
+ });
3895
+
3896
+ // src/ai/prompts/index.ts
3897
+ var init_prompts = __esm({
3898
+ "src/ai/prompts/index.ts"() {
3899
+ "use strict";
3900
+ init_types4();
3901
+ init_generate();
3902
+ init_chat();
3903
+ init_rewrite();
3904
+ init_auto_draft();
3905
+ init_plan();
3906
+ init_agent();
3907
+ init_ask();
3908
+ init_expand_plan();
3909
+ init_search();
3910
+ init_builders();
3911
+ }
3912
+ });
3913
+
3775
3914
  // src/ai/models.ts
3776
3915
  function getModel(id) {
3777
3916
  return AI_MODELS.find((m) => m.id === id);
@@ -4036,6 +4175,70 @@ function safeClose(controller) {
4036
4175
  } catch {
4037
4176
  }
4038
4177
  }
4178
+ function createProviderStream(events, errorPrefix) {
4179
+ const encoder = new TextEncoder();
4180
+ return new ReadableStream({
4181
+ async start(controller) {
4182
+ try {
4183
+ for await (const event of events) {
4184
+ if (event.text) {
4185
+ if (!safeEnqueue(controller, encoder.encode(`data: ${JSON.stringify({ text: event.text })}
4186
+
4187
+ `))) {
4188
+ return;
4189
+ }
4190
+ }
4191
+ if (event.thinking) {
4192
+ if (!safeEnqueue(controller, encoder.encode(`data: ${JSON.stringify({ thinking: event.thinking })}
4193
+
4194
+ `))) {
4195
+ return;
4196
+ }
4197
+ }
4198
+ }
4199
+ safeEnqueue(controller, encoder.encode("data: [DONE]\n\n"));
4200
+ safeClose(controller);
4201
+ } catch (streamError) {
4202
+ const errorMessage = streamError instanceof Error ? streamError.message : "Stream error";
4203
+ console.error(`[${errorPrefix}]`, streamError);
4204
+ safeEnqueue(controller, encoder.encode(`data: ${JSON.stringify({ error: errorMessage })}
4205
+
4206
+ `));
4207
+ safeClose(controller);
4208
+ }
4209
+ }
4210
+ });
4211
+ }
4212
+ async function* normalizeAnthropicEvents(stream) {
4213
+ for await (const event of stream) {
4214
+ if (event.type === "content_block_delta") {
4215
+ const delta = event.delta;
4216
+ if (delta.type === "text_delta" && delta.text) {
4217
+ yield { text: delta.text };
4218
+ } else if (delta.type === "thinking_delta" && delta.thinking) {
4219
+ yield { thinking: delta.thinking };
4220
+ }
4221
+ }
4222
+ }
4223
+ }
4224
+ async function* normalizeOpenAIEvents(stream) {
4225
+ for await (const chunk of stream) {
4226
+ const text = chunk.choices?.[0]?.delta?.content;
4227
+ if (text) {
4228
+ yield { text };
4229
+ }
4230
+ }
4231
+ }
4232
+ async function* normalizeOpenAIResponsesEvents(stream) {
4233
+ for await (const event of stream) {
4234
+ if (event.type === "response.output_text.delta") {
4235
+ const text = event.delta;
4236
+ if (text) {
4237
+ yield { text };
4238
+ }
4239
+ }
4240
+ }
4241
+ }
4039
4242
  async function createAnthropicStream(options, modelId, searchContext = "") {
4040
4243
  const anthropic = new import_sdk.default({
4041
4244
  ...options.anthropicKey && { apiKey: options.anthropicKey }
@@ -4057,39 +4260,7 @@ async function createAnthropicStream(options, modelId, searchContext = "") {
4057
4260
  }
4058
4261
  try {
4059
4262
  const stream = await anthropic.messages.stream(requestParams);
4060
- return new ReadableStream({
4061
- async start(controller) {
4062
- try {
4063
- for await (const event of stream) {
4064
- if (event.type === "content_block_delta") {
4065
- const delta = event.delta;
4066
- if (delta.type === "text_delta" && delta.text) {
4067
- if (!safeEnqueue(controller, new TextEncoder().encode(`data: ${JSON.stringify({ text: delta.text })}
4068
-
4069
- `))) {
4070
- return;
4071
- }
4072
- } else if (delta.type === "thinking_delta" && delta.thinking) {
4073
- if (!safeEnqueue(controller, new TextEncoder().encode(`data: ${JSON.stringify({ thinking: delta.thinking })}
4074
-
4075
- `))) {
4076
- return;
4077
- }
4078
- }
4079
- }
4080
- }
4081
- safeEnqueue(controller, new TextEncoder().encode("data: [DONE]\n\n"));
4082
- safeClose(controller);
4083
- } catch (streamError) {
4084
- const errorMessage = streamError instanceof Error ? streamError.message : "Stream error";
4085
- console.error("[Anthropic Stream Error]", streamError);
4086
- safeEnqueue(controller, new TextEncoder().encode(`data: ${JSON.stringify({ error: errorMessage })}
4087
-
4088
- `));
4089
- safeClose(controller);
4090
- }
4091
- }
4092
- });
4263
+ return createProviderStream(normalizeAnthropicEvents(stream), "Anthropic Stream Error");
4093
4264
  } catch (error) {
4094
4265
  const errorMessage = error instanceof Error ? error.message : "Anthropic API error";
4095
4266
  console.error("[Anthropic API Error]", error);
@@ -4111,31 +4282,7 @@ async function createOpenAIStream(options, modelId, useWebSearch = false) {
4111
4282
  };
4112
4283
  try {
4113
4284
  const stream = await openai.chat.completions.create(requestParams);
4114
- return new ReadableStream({
4115
- async start(controller) {
4116
- try {
4117
- for await (const chunk of stream) {
4118
- const text = chunk.choices[0]?.delta?.content;
4119
- if (text) {
4120
- if (!safeEnqueue(controller, new TextEncoder().encode(`data: ${JSON.stringify({ text })}
4121
-
4122
- `))) {
4123
- return;
4124
- }
4125
- }
4126
- }
4127
- safeEnqueue(controller, new TextEncoder().encode("data: [DONE]\n\n"));
4128
- safeClose(controller);
4129
- } catch (streamError) {
4130
- const errorMessage = streamError instanceof Error ? streamError.message : "Stream error";
4131
- console.error("[OpenAI Stream Error]", streamError);
4132
- safeEnqueue(controller, new TextEncoder().encode(`data: ${JSON.stringify({ error: errorMessage })}
4133
-
4134
- `));
4135
- safeClose(controller);
4136
- }
4137
- }
4138
- });
4285
+ return createProviderStream(normalizeOpenAIEvents(stream), "OpenAI Stream Error");
4139
4286
  } catch (error) {
4140
4287
  const errorMessage = error instanceof Error ? error.message : "OpenAI API error";
4141
4288
  console.error("[OpenAI API Error]", error);
@@ -4162,33 +4309,7 @@ ${lastUserMessage}`;
4162
4309
  tools: [{ type: "web_search" }],
4163
4310
  stream: true
4164
4311
  });
4165
- return new ReadableStream({
4166
- async start(controller) {
4167
- try {
4168
- for await (const event of response) {
4169
- if (event.type === "response.output_text.delta") {
4170
- const text = event.delta;
4171
- if (text) {
4172
- if (!safeEnqueue(controller, new TextEncoder().encode(`data: ${JSON.stringify({ text })}
4173
-
4174
- `))) {
4175
- return;
4176
- }
4177
- }
4178
- }
4179
- }
4180
- safeEnqueue(controller, new TextEncoder().encode("data: [DONE]\n\n"));
4181
- safeClose(controller);
4182
- } catch (streamError) {
4183
- const errorMessage = streamError instanceof Error ? streamError.message : "Stream error";
4184
- console.error("[OpenAI Responses Stream Error]", streamError);
4185
- safeEnqueue(controller, new TextEncoder().encode(`data: ${JSON.stringify({ error: errorMessage })}
4186
-
4187
- `));
4188
- safeClose(controller);
4189
- }
4190
- }
4191
- });
4312
+ return createProviderStream(normalizeOpenAIResponsesEvents(response), "OpenAI Responses Stream Error");
4192
4313
  } catch (error) {
4193
4314
  const errorMessage = error instanceof Error ? error.message : "OpenAI Responses API error";
4194
4315
  console.error("[OpenAI Responses API Error]", error);
@@ -4209,17 +4330,17 @@ var init_provider = __esm({
4209
4330
  var builders_exports = {};
4210
4331
  __export(builders_exports, {
4211
4332
  buildAutoDraftPrompt: () => buildAutoDraftPrompt,
4212
- buildChatPrompt: () => buildChatPrompt,
4213
- buildExpandPlanPrompt: () => buildExpandPlanPrompt,
4214
- buildGeneratePrompt: () => buildGeneratePrompt,
4215
- buildPlanPrompt: () => buildPlanPrompt,
4216
- buildRewritePrompt: () => buildRewritePrompt
4333
+ buildChatPrompt: () => buildChatPrompt2,
4334
+ buildExpandPlanPrompt: () => buildExpandPlanPrompt2,
4335
+ buildGeneratePrompt: () => buildGeneratePrompt2,
4336
+ buildPlanPrompt: () => buildPlanPrompt2,
4337
+ buildRewritePrompt: () => buildRewritePrompt2
4217
4338
  });
4218
- function buildGeneratePrompt(options) {
4339
+ function buildGeneratePrompt2(options) {
4219
4340
  const template = options.template || DEFAULT_GENERATE_TEMPLATE;
4220
4341
  return template.replace("{{RULES}}", options.rules || "").replace("{{WORD_COUNT}}", String(options.wordCount || 800)).replace("{{STYLE_EXAMPLES}}", options.styleExamples || "");
4221
4342
  }
4222
- function buildChatPrompt(options) {
4343
+ function buildChatPrompt2(options) {
4223
4344
  const template = options.template || DEFAULT_CHAT_TEMPLATE;
4224
4345
  let essaySection = "";
4225
4346
  if (options.essayContext) {
@@ -4234,16 +4355,16 @@ ${options.essayContext.markdown}
4234
4355
  }
4235
4356
  return template.replace("{{CHAT_RULES}}", options.chatRules || "").replace("{{RULES}}", options.rules || "").replace("{{ESSAY_CONTEXT}}", essaySection).replace("{{STYLE_EXAMPLES}}", options.styleExamples || "");
4236
4357
  }
4237
- function buildExpandPlanPrompt(options) {
4358
+ function buildExpandPlanPrompt2(options) {
4238
4359
  const template = options.template || DEFAULT_EXPAND_PLAN_TEMPLATE;
4239
4360
  return template.replace("{{RULES}}", options.rules || "").replace("{{STYLE_EXAMPLES}}", options.styleExamples || "").replace("{{PLAN}}", options.plan);
4240
4361
  }
4241
- function buildPlanPrompt(options) {
4362
+ function buildPlanPrompt2(options) {
4242
4363
  const template = options.template || DEFAULT_PLAN_TEMPLATE;
4243
4364
  const rules = options.planRules || DEFAULT_PLAN_RULES;
4244
4365
  return template.replace("{{PLAN_RULES}}", rules).replace("{{STYLE_EXAMPLES}}", options.styleExamples || "");
4245
4366
  }
4246
- function buildRewritePrompt(options) {
4367
+ function buildRewritePrompt2(options) {
4247
4368
  const template = options.template || DEFAULT_REWRITE_TEMPLATE;
4248
4369
  return template.replace("{{REWRITE_RULES}}", options.rewriteRules || "").replace("{{RULES}}", options.rules || "").replace("{{STYLE_EXAMPLES}}", options.styleExamples || "");
4249
4370
  }
@@ -4251,7 +4372,7 @@ function buildAutoDraftPrompt(options) {
4251
4372
  const template = options.template || DEFAULT_AUTO_DRAFT_TEMPLATE;
4252
4373
  return template.replace("{{AUTO_DRAFT_RULES}}", options.autoDraftRules || "").replace("{{RULES}}", options.rules || "").replace("{{AUTO_DRAFT_WORD_COUNT}}", String(options.wordCount || 800)).replace("{{STYLE_EXAMPLES}}", options.styleExamples || "").replace("{{TOPIC_NAME}}", options.topicName || "").replace("{{ARTICLE_TITLE}}", options.articleTitle || "").replace("{{ARTICLE_SUMMARY}}", options.articleSummary || "").replace("{{ARTICLE_URL}}", options.articleUrl || "");
4253
4374
  }
4254
- var init_builders = __esm({
4375
+ var init_builders2 = __esm({
4255
4376
  "src/ai/builders.ts"() {
4256
4377
  "use strict";
4257
4378
  init_prompts();
@@ -4487,7 +4608,7 @@ __export(generate_exports, {
4487
4608
  generateStream: () => generateStream
4488
4609
  });
4489
4610
  async function generateStream(options) {
4490
- const systemPrompt = buildGeneratePrompt({
4611
+ const systemPrompt = buildGeneratePrompt2({
4491
4612
  rules: options.rules,
4492
4613
  template: options.template,
4493
4614
  wordCount: options.wordCount,
@@ -4528,7 +4649,7 @@ Use the source material above as reference for the essay.`;
4528
4649
  });
4529
4650
  }
4530
4651
  async function expandPlanStream(options) {
4531
- const systemPrompt = buildExpandPlanPrompt({
4652
+ const systemPrompt = buildExpandPlanPrompt2({
4532
4653
  rules: options.rules,
4533
4654
  template: options.template,
4534
4655
  plan: options.plan,
@@ -4545,11 +4666,11 @@ async function expandPlanStream(options) {
4545
4666
  maxTokens: 8192
4546
4667
  });
4547
4668
  }
4548
- var init_generate = __esm({
4669
+ var init_generate2 = __esm({
4549
4670
  "src/ai/generate.ts"() {
4550
4671
  "use strict";
4551
4672
  init_provider();
4552
- init_builders();
4673
+ init_builders2();
4553
4674
  init_url_extractor();
4554
4675
  }
4555
4676
  });
@@ -4560,11 +4681,11 @@ __export(chat_exports, {
4560
4681
  chatStream: () => chatStream
4561
4682
  });
4562
4683
  async function chatStream(options) {
4563
- const systemPrompt = options.mode === "plan" ? buildPlanPrompt({
4684
+ const systemPrompt = options.mode === "plan" ? buildPlanPrompt2({
4564
4685
  planRules: options.planRules,
4565
4686
  template: options.planTemplate,
4566
4687
  styleExamples: options.styleExamples
4567
- }) : buildChatPrompt({
4688
+ }) : buildChatPrompt2({
4568
4689
  chatRules: options.chatRules,
4569
4690
  rules: options.rules,
4570
4691
  template: options.template,
@@ -4613,6 +4734,8 @@ URL extraction encountered an error: ${err instanceof Error ? err.message : "Unk
4613
4734
  let modeInstructions = "";
4614
4735
  if (options.mode === "agent") {
4615
4736
  modeInstructions = "\n\n" + (options.agentTemplate || DEFAULT_AGENT_TEMPLATE);
4737
+ } else if (options.mode === "ask" || !options.mode) {
4738
+ modeInstructions = "\n\n" + DEFAULT_ASK_TEMPLATE;
4616
4739
  }
4617
4740
  let webSearchContext = "";
4618
4741
  if (options.useWebSearch) {
@@ -4663,11 +4786,11 @@ If the fetch failed, explain what happened using the error details provided.
4663
4786
  useWebSearch: options.useWebSearch
4664
4787
  });
4665
4788
  }
4666
- var init_chat = __esm({
4789
+ var init_chat2 = __esm({
4667
4790
  "src/ai/chat.ts"() {
4668
4791
  "use strict";
4669
4792
  init_provider();
4670
- init_builders();
4793
+ init_builders2();
4671
4794
  init_url_extractor();
4672
4795
  init_prompts();
4673
4796
  }
@@ -4688,11 +4811,11 @@ __export(src_exports, {
4688
4811
  addCommentMark: () => addCommentMark,
4689
4812
  applyCommentMarks: () => applyCommentMarks,
4690
4813
  buildAutoDraftPrompt: () => buildAutoDraftPrompt,
4691
- buildChatPrompt: () => buildChatPrompt,
4692
- buildExpandPlanPrompt: () => buildExpandPlanPrompt,
4693
- buildGeneratePrompt: () => buildGeneratePrompt,
4694
- buildPlanPrompt: () => buildPlanPrompt,
4695
- buildRewritePrompt: () => buildRewritePrompt,
4814
+ buildChatPrompt: () => buildChatPrompt2,
4815
+ buildExpandPlanPrompt: () => buildExpandPlanPrompt2,
4816
+ buildGeneratePrompt: () => buildGeneratePrompt2,
4817
+ buildPlanPrompt: () => buildPlanPrompt2,
4818
+ buildRewritePrompt: () => buildRewritePrompt2,
4696
4819
  canDeleteComment: () => canDeleteComment,
4697
4820
  canEditComment: () => canEditComment,
4698
4821
  createAPIHandler: () => createAPIHandler,
@@ -4727,6 +4850,14 @@ __export(src_exports, {
4727
4850
  });
4728
4851
  module.exports = __toCommonJS(src_exports);
4729
4852
 
4853
+ // src/types/models.ts
4854
+ var PostStatus = {
4855
+ DRAFT: "draft",
4856
+ PUBLISHED: "published",
4857
+ DELETED: "deleted",
4858
+ SUGGESTED: "suggested"
4859
+ };
4860
+
4730
4861
  // src/destinations/prismic.ts
4731
4862
  function mapPostToStub(_post) {
4732
4863
  return {};
@@ -4876,7 +5007,7 @@ function createPostsData(prisma, hooks, dispatcher, prismicEnvToken) {
4876
5007
  },
4877
5008
  async findPublished() {
4878
5009
  return prisma.post.findMany({
4879
- where: { status: "published" },
5010
+ where: { status: PostStatus.PUBLISHED },
4880
5011
  orderBy: { publishedAt: "desc" }
4881
5012
  });
4882
5013
  },
@@ -4894,7 +5025,7 @@ function createPostsData(prisma, hooks, dispatcher, prismicEnvToken) {
4894
5025
  },
4895
5026
  async findDrafts() {
4896
5027
  return prisma.post.findMany({
4897
- where: { status: "draft" },
5028
+ where: { status: PostStatus.DRAFT },
4898
5029
  orderBy: { updatedAt: "desc" }
4899
5030
  });
4900
5031
  },
@@ -4918,7 +5049,7 @@ function createPostsData(prisma, hooks, dispatcher, prismicEnvToken) {
4918
5049
  ...postData,
4919
5050
  slug,
4920
5051
  markdown: postData.markdown || "",
4921
- status: postData.status || "draft"
5052
+ status: postData.status || PostStatus.DRAFT
4922
5053
  }
4923
5054
  });
4924
5055
  if (tagIds?.length) {
@@ -4958,8 +5089,8 @@ function createPostsData(prisma, hooks, dispatcher, prismicEnvToken) {
4958
5089
  const hasDestinationChanges = existing && (postData.title !== void 0 && postData.title !== existing.title || postData.slug !== void 0 && postData.slug !== existing.slug || postData.markdown !== void 0 && postData.markdown !== existing.markdown);
4959
5090
  const hasSlugChange = existing && postData.slug !== void 0 && postData.slug !== existing.slug;
4960
5091
  const hasTitleChange = existing && postData.title !== void 0 && postData.title !== existing.title;
4961
- if (postData.status === "published") {
4962
- if (existing?.status !== "published") {
5092
+ if (postData.status === PostStatus.PUBLISHED) {
5093
+ if (existing?.status !== PostStatus.PUBLISHED) {
4963
5094
  postData.publishedAt = /* @__PURE__ */ new Date();
4964
5095
  isPublishing = true;
4965
5096
  if (hooks?.beforePublish) {
@@ -4968,11 +5099,11 @@ function createPostsData(prisma, hooks, dispatcher, prismicEnvToken) {
4968
5099
  } else if (hasDestinationChanges) {
4969
5100
  isUpdatingPublished = true;
4970
5101
  }
4971
- } else if (postData.status === "draft") {
4972
- if (existing?.status === "published") {
5102
+ } else if (postData.status === PostStatus.DRAFT) {
5103
+ if (existing?.status === PostStatus.PUBLISHED) {
4973
5104
  isUnpublishing = true;
4974
5105
  }
4975
- } else if (postData.status === void 0 && existing?.status === "published" && hasDestinationChanges) {
5106
+ } else if (postData.status === void 0 && existing?.status === PostStatus.PUBLISHED && hasDestinationChanges) {
4976
5107
  isUpdatingPublished = true;
4977
5108
  }
4978
5109
  if (postData.slug) {
@@ -5040,9 +5171,9 @@ function createPostsData(prisma, hooks, dispatcher, prismicEnvToken) {
5040
5171
  });
5041
5172
  const result = await prisma.post.update({
5042
5173
  where: { id },
5043
- data: { status: "deleted" }
5174
+ data: { status: PostStatus.DELETED }
5044
5175
  });
5045
- if (existing?.status === "published") {
5176
+ if (existing?.status === PostStatus.PUBLISHED) {
5046
5177
  if (dispatcher) {
5047
5178
  dispatcher.delete(existing).catch((err) => {
5048
5179
  console.error("[autoblogger] Failed to dispatch delete event:", err);
@@ -5565,7 +5696,7 @@ function createNewsItemsData(prisma) {
5565
5696
  const post = await createPost({
5566
5697
  title: newsItem.title,
5567
5698
  markdown: newsItem.summary || "",
5568
- status: "suggested",
5699
+ status: PostStatus.SUGGESTED,
5569
5700
  sourceUrl: newsItem.url,
5570
5701
  topicId: newsItem.topicId
5571
5702
  });
@@ -5661,7 +5792,7 @@ async function handlePostsAPI(req, cms, session, path, onMutate) {
5661
5792
  }
5662
5793
  if (method === "PATCH" && postId) {
5663
5794
  const body = await req.json();
5664
- if (body.status === "published" && !cms.config.auth.canPublish(session)) {
5795
+ if (body.status === PostStatus.PUBLISHED && !cms.config.auth.canPublish(session)) {
5665
5796
  return jsonResponse({ error: "Not authorized to publish" }, 403);
5666
5797
  }
5667
5798
  const contentChanging = body.title !== void 0 || body.subtitle !== void 0 || body.markdown !== void 0;
@@ -5888,7 +6019,7 @@ async function handleAIAPI(req, cms, session, path) {
5888
6019
  if (!styleExamples) {
5889
6020
  styleExamples = await fetchStyleExamples(cms);
5890
6021
  }
5891
- const { expandPlanStream: expandPlanStream2 } = await Promise.resolve().then(() => (init_generate(), generate_exports));
6022
+ const { expandPlanStream: expandPlanStream2 } = await Promise.resolve().then(() => (init_generate2(), generate_exports));
5892
6023
  stream = await expandPlanStream2({
5893
6024
  plan,
5894
6025
  model: model || settings.defaultModel,
@@ -5903,7 +6034,7 @@ async function handleAIAPI(req, cms, session, path) {
5903
6034
  if (!styleExamples) {
5904
6035
  styleExamples = await fetchStyleExamples(cms);
5905
6036
  }
5906
- const { generateStream: generateStream2 } = await Promise.resolve().then(() => (init_generate(), generate_exports));
6037
+ const { generateStream: generateStream2 } = await Promise.resolve().then(() => (init_generate2(), generate_exports));
5907
6038
  stream = await generateStream2({
5908
6039
  prompt,
5909
6040
  model: model || settings.defaultModel,
@@ -5993,7 +6124,7 @@ ${examples}
5993
6124
  } catch (err) {
5994
6125
  console.error("[AI Chat] Failed to fetch published essays:", err);
5995
6126
  }
5996
- const { chatStream: chatStream2 } = await Promise.resolve().then(() => (init_chat(), chat_exports));
6127
+ const { chatStream: chatStream2 } = await Promise.resolve().then(() => (init_chat2(), chat_exports));
5997
6128
  try {
5998
6129
  const stream = await chatStream2({
5999
6130
  messages,
@@ -6054,7 +6185,7 @@ ${truncatedContent}`;
6054
6185
  } catch (err) {
6055
6186
  console.error("[AI Rewrite] Failed to fetch published essays:", err);
6056
6187
  }
6057
- const { buildRewritePrompt: buildRewritePrompt3 } = await Promise.resolve().then(() => (init_builders(), builders_exports));
6188
+ const { buildRewritePrompt: buildRewritePrompt3 } = await Promise.resolve().then(() => (init_builders2(), builders_exports));
6058
6189
  const { createStream: createStream2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
6059
6190
  try {
6060
6191
  const systemPrompt = buildRewritePrompt3({
@@ -6665,9 +6796,9 @@ function filterByKeywords(articles, keywords) {
6665
6796
  // src/ai/index.ts
6666
6797
  init_models();
6667
6798
  init_provider();
6668
- init_generate();
6669
- init_chat();
6670
- init_builders();
6799
+ init_generate2();
6800
+ init_chat2();
6801
+ init_builders2();
6671
6802
  init_prompts();
6672
6803
 
6673
6804
  // src/ai/parse.ts
@@ -6711,79 +6842,6 @@ function renderMarkdown(markdown) {
6711
6842
  function markdownToHtml(markdown) {
6712
6843
  return import_marked.marked.parse(markdown, { gfm: true, breaks: true });
6713
6844
  }
6714
- function createStyledRenderer() {
6715
- const renderer = new import_marked.Renderer();
6716
- renderer.heading = function(text, level) {
6717
- const classes = {
6718
- 1: "text-[22px] leading-tight font-bold mb-4",
6719
- 2: "text-lg leading-snug font-bold mt-6 mb-3",
6720
- 3: "text-base leading-snug font-bold mt-4 mb-2",
6721
- 4: "text-sm leading-snug font-semibold mt-3 mb-1",
6722
- 5: "text-sm leading-snug font-semibold mt-2 mb-1",
6723
- 6: "text-sm leading-snug font-medium mt-2 mb-1"
6724
- };
6725
- return `<h${level} class="${classes[level] || ""}">${text}</h${level}>
6726
- `;
6727
- };
6728
- renderer.paragraph = function(text) {
6729
- return `<p class="mb-3 leading-relaxed">${text}</p>
6730
- `;
6731
- };
6732
- renderer.list = function(body, ordered) {
6733
- const tag = ordered ? "ol" : "ul";
6734
- const listClass = ordered ? "list-decimal" : "list-disc";
6735
- return `<${tag} class="${listClass} pl-5 mb-3 space-y-1">${body}</${tag}>
6736
- `;
6737
- };
6738
- renderer.listitem = function(text) {
6739
- return `<li>${text}</li>
6740
- `;
6741
- };
6742
- renderer.code = function(code, language) {
6743
- const escaped = code.replace(/</g, "&lt;").replace(/>/g, "&gt;");
6744
- return `<pre class="bg-gray-100 dark:bg-gray-800 p-3 rounded-lg overflow-x-auto mb-3 text-sm font-mono"><code class="language-${language || ""}">${escaped}</code></pre>
6745
- `;
6746
- };
6747
- renderer.codespan = function(text) {
6748
- return `<code class="bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded text-sm font-mono">${text}</code>`;
6749
- };
6750
- renderer.blockquote = function(quote) {
6751
- return `<blockquote class="border-l-4 border-gray-300 dark:border-gray-600 pl-4 italic text-gray-600 dark:text-gray-400 my-3">${quote}</blockquote>
6752
- `;
6753
- };
6754
- renderer.hr = function() {
6755
- return `<hr class="my-6 border-t border-gray-200 dark:border-gray-700" />
6756
- `;
6757
- };
6758
- renderer.link = function(href, _title, text) {
6759
- return `<a href="${href}" class="text-blue-600 dark:text-blue-400 underline">${text}</a>`;
6760
- };
6761
- renderer.image = function(href, _title, text) {
6762
- return `<img src="${href}" alt="${text}" class="rounded-lg max-w-full my-3" />`;
6763
- };
6764
- renderer.strong = function(text) {
6765
- return `<strong class="font-semibold">${text}</strong>`;
6766
- };
6767
- renderer.em = function(text) {
6768
- return `<em class="italic">${text}</em>`;
6769
- };
6770
- renderer.table = function(header, body) {
6771
- return `<table class="w-full border-collapse mb-3"><thead>${header}</thead><tbody>${body}</tbody></table>
6772
- `;
6773
- };
6774
- renderer.tablerow = function(content) {
6775
- return `<tr>${content}</tr>
6776
- `;
6777
- };
6778
- renderer.tablecell = function(content, flags) {
6779
- const tag = flags.header ? "th" : "td";
6780
- const headerClass = flags.header ? " font-semibold bg-gray-50 dark:bg-gray-800" : "";
6781
- const alignClass = flags.align ? ` text-${flags.align}` : " text-left";
6782
- return `<${tag} class="border border-gray-200 dark:border-gray-700 px-3 py-2${alignClass}${headerClass}">${content}</${tag}>`;
6783
- };
6784
- return renderer;
6785
- }
6786
- var styledRenderer = createStyledRenderer();
6787
6845
  function parseMarkdown(markdown) {
6788
6846
  return import_marked.marked.lexer(markdown);
6789
6847
  }
@@ -6825,7 +6883,7 @@ function renderMarkdownSanitized(markdown) {
6825
6883
  async function getStyleContext(prisma) {
6826
6884
  const settings = await prisma.aISettings.findUnique({ where: { id: "default" } });
6827
6885
  const posts = await prisma.post.findMany({
6828
- where: { status: "published" },
6886
+ where: { status: PostStatus.PUBLISHED },
6829
6887
  select: { title: true, subtitle: true, markdown: true },
6830
6888
  orderBy: { publishedAt: "desc" },
6831
6889
  take: 10
@@ -6947,7 +7005,7 @@ async function runAutoDraft(config, topicId, skipFrequencyCheck = false) {
6947
7005
  subtitle: essay.subtitle,
6948
7006
  slug,
6949
7007
  markdown: essay.markdown,
6950
- status: "suggested",
7008
+ status: PostStatus.SUGGESTED,
6951
7009
  sourceUrl: article.url,
6952
7010
  topicId: topic.id,
6953
7011
  ...extraFields