Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions web/src/kernel/router.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createLLMProviderFactory } from '@stackbilt/llm-providers';
import { getProcedure, findNearMiss, procedureKey, PROCEDURE_MIN_SUCCESSES, PROCEDURE_MIN_SUCCESS_RATE, getConversationHistory } from './memory/index.js';
import { askGroq, askGroqWithLogprobs } from '../groq.js';
import type { KernelIntent, ExecutionPlan, Executor } from './types.js';
Expand Down Expand Up @@ -73,21 +74,21 @@ async function classifyWithWorkersAI(
systemPrompt: string,
userPrompt: string,
): Promise<string> {
const result = await ai.run('@cf/meta/llama-3.2-3b-instruct', {
const result = await createLLMProviderFactory({
cloudflare: { ai },
fallbackRules: [],
enableCircuitBreaker: true,
enableRetries: true,
}).generateResponse({
model: '@cf/meta/llama-3.1-8b-instruct',
systemPrompt,
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt },
],
max_tokens: 200,
maxTokens: 200,
temperature: 0.1,
}) as { response?: unknown };
const raw = result.response;
if (typeof raw === 'string') return raw;
if (raw == null) return '';
// Workers AI sometimes returns structured responses (objects with tool_calls,
// arrays of segments, etc.). Coerce to string so downstream .trim()/JSON.parse
// callers don't crash on non-string payloads.
return typeof raw === 'object' ? JSON.stringify(raw) : String(raw);
});
return result.message ?? '';
}


Expand Down
16 changes: 9 additions & 7 deletions web/src/kernel/scheduled/conversation-facts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Workers AI llama-3.1-8b (free tier) as fallback.

import { type EdgeEnv } from '../dispatch.js';
import { buildLLMProviderFactory } from '../provider-factory.js';
import { recordMemory as recordMemoryAdapter } from '../memory-adapter.js';
import { askGroq } from '../../groq.js';
import { pushFactsToMindSpring, type FactEntry } from './mindspring-notebook.js';
Expand Down Expand Up @@ -97,13 +98,14 @@ async function askAi(
}
// Workers AI fallback — llama-3.1-8b is on the genuine free tier
if (env.ai) {
const result = await env.ai.run(
'@cf/meta/llama-3.1-8b-instruct' as Parameters<Ai['run']>[0],
{ messages: [{ role: 'system', content: system }, { role: 'user', content: user }] },
);
if (typeof result === 'string') return result;
const obj = result as { response?: string; choices?: Array<{ message?: { content?: string } }> };
return obj.choices?.[0]?.message?.content ?? obj.response ?? '';
const result = await buildLLMProviderFactory(env).generateResponse({
model: '@cf/meta/llama-3.1-8b-instruct',
systemPrompt: system,
messages: [{ role: 'user', content: user }],
maxTokens: 1024,
temperature: 0.2,
});
return result.message ?? '';
}
throw new Error('[conv-facts] No LLM provider available (groqApiKey and env.ai both missing)');
}
Expand Down
14 changes: 9 additions & 5 deletions web/src/kernel/scheduled/dreaming/llm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Shared LLM helper — Groq first (free, 70B quality), Workers AI 70B fallback

import type { EdgeEnv } from '../../dispatch.js';
import { buildLLMProviderFactory } from '../../provider-factory.js';
import { askGroq } from '../../../groq.js';

export async function askWorkersAiOrGroq(
Expand All @@ -20,11 +21,14 @@ export async function askWorkersAiOrGroq(
}
// Workers AI fallback — only fires if Groq is unavailable or throws
if (env.ai) {
const result = await env.ai.run(
'@cf/meta/llama-3.3-70b-instruct-fp8-fast' as Parameters<Ai['run']>[0],
{ messages: [{ role: 'system', content: system }, { role: 'user', content: user }] },
) as { response?: string; choices?: Array<{ message?: { content?: string } }> };
return result.choices?.[0]?.message?.content ?? result.response ?? '';
const result = await buildLLMProviderFactory(env).generateResponse({
model: '@cf/meta/llama-3.3-70b-instruct-fp8-fast',
systemPrompt: system,
messages: [{ role: 'user', content: user }],
maxTokens: 2048,
temperature: 0.2,
});
return result.message ?? '';
}
throw new Error('[dreaming] No LLM provider available (groqApiKey and env.ai both missing)');
}
Expand Down
20 changes: 12 additions & 8 deletions web/src/kernel/scheduled/social-engage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Runs every 6 hours. Likes replies, follows back real accounts,
// replies to substantive comments with Workers AI.

import { createLLMProviderFactory } from '@stackbilt/llm-providers';
import { type EdgeEnv } from '../dispatch.js';
import {
getNotifications,
Expand Down Expand Up @@ -153,21 +154,24 @@ async function generateReply(
incomingText: string,
authorHandle: string,
): Promise<string | null> {
const result = await ai.run('@cf/meta/llama-3.1-8b-instruct' as Parameters<Ai['run']>[0], {
const result = await createLLMProviderFactory({
cloudflare: { ai },
fallbackRules: [],
enableCircuitBreaker: true,
enableRetries: true,
}).generateResponse({
model: '@cf/meta/llama-3.1-8b-instruct',
systemPrompt: `You are the operator's social media voice. Direct, builder-energy, anti-corporate. No emoji spam. No "excited to announce." Keep replies under 200 chars. Be genuine and conversational. If you can't add value, return SKIP.`,
messages: [
{
role: 'system',
content: `You are the operator's social media voice. Direct, builder-energy, anti-corporate. No emoji spam. No "excited to announce." Keep replies under 200 chars. Be genuine and conversational. If you can't add value, return SKIP.`,
},
{
role: 'user',
content: `@${authorHandle} replied to our Bluesky post: "${incomingText}"\n\nWrite a brief, genuine reply. Return ONLY the reply text, or SKIP if there's nothing meaningful to add.`,
},
],
max_tokens: 100,
}) as { response?: string };
maxTokens: 100,
});

const reply = result.response?.trim();
const reply = result.message?.trim();
if (!reply || reply === 'SKIP' || reply.length < 5) return null;

// Safety: truncate to 300 chars (Bluesky limit)
Expand Down