docs(web): refresh v0.8.32 site state

This commit is contained in:
Hunter Bown
2026-05-12 14:04:17 -05:00
parent b25450728e
commit 190eb6b162
10 changed files with 155 additions and 264 deletions
+2
View File
@@ -57,6 +57,8 @@ export async function GET(req: Request) {
const agentEnv: AgentEnv = {
CURATED_KV: env.CURATED_KV,
DEEPSEEK_API_KEY: env.DEEPSEEK_API_KEY,
DEEPSEEK_BASE_URL: env.DEEPSEEK_BASE_URL ?? process.env.DEEPSEEK_BASE_URL,
DEEPSEEK_MODEL: env.DEEPSEEK_MODEL ?? process.env.DEEPSEEK_MODEL,
GITHUB_TOKEN: env.GITHUB_TOKEN,
CRON_SECRET: env.CRON_SECRET,
GITHUB_REPO: env.GITHUB_REPO,
+21 -6
View File
@@ -12,6 +12,7 @@ import {
hasFreshDraft,
logUsage,
type AgentDraft,
type DeepSeekEnv,
} from "@/lib/community-agent";
export interface AgentEnv {
@@ -22,6 +23,8 @@ export interface AgentEnv {
delete(key: string): Promise<void>;
};
DEEPSEEK_API_KEY?: string;
DEEPSEEK_BASE_URL?: string;
DEEPSEEK_MODEL?: string;
GITHUB_TOKEN?: string;
CRON_SECRET?: string;
GITHUB_REPO?: string;
@@ -29,6 +32,13 @@ export interface AgentEnv {
MAINTAINER_GITHUB_PAT?: string;
}
function dsEnv(env: AgentEnv): DeepSeekEnv {
return {
baseUrl: env.DEEPSEEK_BASE_URL ?? process.env.DEEPSEEK_BASE_URL,
model: env.DEEPSEEK_MODEL ?? process.env.DEEPSEEK_MODEL,
};
}
export async function runCurate(env: AgentEnv): Promise<Record<string, unknown>> {
if (!env.DEEPSEEK_API_KEY) {
return { skipped: true, reason: "DEEPSEEK_API_KEY not set" };
@@ -38,7 +48,7 @@ export async function runCurate(env: AgentEnv): Promise<Record<string, unknown>>
fetchRepoStats(env.GITHUB_TOKEN),
fetchFeed(env.GITHUB_TOKEN, 30),
]);
const dispatch = await curate(env.DEEPSEEK_API_KEY, stats, feed);
const dispatch = await curate(env.DEEPSEEK_API_KEY, stats, feed, dsEnv(env));
await putDispatch(dispatch);
return { ok: true, headline: dispatch.headline };
} catch (e) {
@@ -84,7 +94,8 @@ export async function runTriage(env: AgentEnv): Promise<Record<string, unknown>>
const { content, usage } = await agentChat(
[{ role: "system", content: TRIAGE_PROMPT }, { role: "user", content: JSON.stringify(payload) }],
env.DEEPSEEK_API_KEY!,
true
true,
dsEnv(env)
);
const parsed = JSON.parse(content) as { bodyEn: string; bodyZh: string };
const draft: AgentDraft = {
@@ -166,7 +177,8 @@ export async function runPrReview(env: AgentEnv): Promise<Record<string, unknown
const { content, usage } = await agentChat(
[{ role: "system", content: PR_REVIEW_PROMPT }, { role: "user", content: JSON.stringify(payload) }],
env.DEEPSEEK_API_KEY!,
true
true,
dsEnv(env)
);
const parsed = JSON.parse(content) as { bodyEn: string; bodyZh: string };
const draft: AgentDraft = {
@@ -232,7 +244,8 @@ export async function runStale(env: AgentEnv): Promise<Record<string, unknown>>
const { content, usage } = await agentChat(
[{ role: "system", content: STALE_PROMPT }, { role: "user", content: JSON.stringify(payload) }],
env.DEEPSEEK_API_KEY!,
true
true,
dsEnv(env)
);
const parsed = JSON.parse(content) as { bodyEn: string; bodyZh: string };
const draft: AgentDraft = {
@@ -290,7 +303,8 @@ export async function runDupes(env: AgentEnv): Promise<Record<string, unknown>>
const { content, usage } = await agentChat(
[{ role: "system", content: DUPES_PROMPT }, { role: "user", content: JSON.stringify({ issues: openIssues }) }],
env.DEEPSEEK_API_KEY!,
true
true,
dsEnv(env)
);
const parsed = JSON.parse(content) as { suggestions?: { targetNumber: number; duplicateNumber: number; reason: string; bodyEn: string; bodyZh: string }[] };
@@ -373,7 +387,8 @@ export async function runDigest(env: AgentEnv): Promise<Record<string, unknown>>
const { content, usage } = await agentChat(
[{ role: "system", content: DIGEST_PROMPT }, { role: "user", content: JSON.stringify(payload) }],
env.DEEPSEEK_API_KEY!,
true
true,
dsEnv(env)
);
const parsed = JSON.parse(content) as { titleEn: string; titleZh: string; summaryEn: string; summaryZh: string; sections: { heading: string; items: string[] }[] };
+13 -3
View File
@@ -41,13 +41,19 @@ export interface UsageLog {
outputTokens: number;
}
export interface DeepSeekEnv {
baseUrl?: string;
model?: string;
}
export async function agentChat(
messages: ChatMessage[],
apiKey: string,
jsonMode = false
jsonMode = false,
dsEnv?: DeepSeekEnv
): Promise<{ content: string; usage: { input: number; output: number } }> {
const base = process.env.DEEPSEEK_BASE_URL ?? FALLBACK_BASE;
const model = process.env.DEEPSEEK_MODEL ?? FALLBACK_MODEL;
const base = dsEnv?.baseUrl ?? process.env.DEEPSEEK_BASE_URL ?? FALLBACK_BASE;
const model = dsEnv?.model ?? process.env.DEEPSEEK_MODEL ?? FALLBACK_MODEL;
const res = await fetch(`${base}/v1/chat/completions`, {
method: "POST",
headers: {
@@ -185,6 +191,8 @@ interface KVNamespace {
export interface CommunityAgentEnv {
CURATED_KV?: KVNamespace;
DEEPSEEK_API_KEY?: string;
DEEPSEEK_BASE_URL?: string;
DEEPSEEK_MODEL?: string;
GITHUB_TOKEN?: string;
CRON_SECRET?: string;
GITHUB_REPO?: string;
@@ -200,6 +208,8 @@ export async function getAgentEnv(): Promise<CommunityAgentEnv> {
} catch {
return {
DEEPSEEK_API_KEY: process.env.DEEPSEEK_API_KEY,
DEEPSEEK_BASE_URL: process.env.DEEPSEEK_BASE_URL,
DEEPSEEK_MODEL: process.env.DEEPSEEK_MODEL,
GITHUB_TOKEN: process.env.GITHUB_TOKEN,
CRON_SECRET: process.env.CRON_SECRET,
GITHUB_REPO: process.env.GITHUB_REPO,
+11 -1
View File
@@ -13,7 +13,7 @@
* Both surface as drafts in CURATED_KV under `draft:linkcheck:<...>` and
* `draft:semantic-drift:<...>`, picked up by the existing /admin listing.
*/
import { agentChat, saveDraft, type AgentDraft, VOICE_CONSTRAINTS } from "./community-agent";
import { agentChat, saveDraft, type AgentDraft, type DeepSeekEnv, VOICE_CONSTRAINTS } from "./community-agent";
interface KVNamespace {
get(k: string): Promise<string | null>;
@@ -25,9 +25,18 @@ interface KVNamespace {
interface WatchEnv {
CURATED_KV?: KVNamespace;
DEEPSEEK_API_KEY?: string;
DEEPSEEK_BASE_URL?: string;
DEEPSEEK_MODEL?: string;
GITHUB_TOKEN?: string;
}
function dsEnv(env: WatchEnv): DeepSeekEnv {
return {
baseUrl: env.DEEPSEEK_BASE_URL ?? process.env.DEEPSEEK_BASE_URL,
model: env.DEEPSEEK_MODEL ?? process.env.DEEPSEEK_MODEL,
};
}
// --- Link checker ---
// Targets to probe daily. For registries that block bot HEAD/GET (npm, crates.io)
@@ -255,6 +264,7 @@ ${docsText}`;
],
env.DEEPSEEK_API_KEY,
true,
dsEnv(env),
);
} catch (e) {
return { ok: false, drafted: 0, reason: `LLM call failed: ${e}` };
+17 -5
View File
@@ -12,9 +12,19 @@ interface ChatResponse {
choices: { message: { content: string } }[];
}
export async function chat(messages: ChatMessage[], apiKey: string, jsonMode = false): Promise<string> {
const base = process.env.DEEPSEEK_BASE_URL ?? FALLBACK_BASE;
const model = process.env.DEEPSEEK_MODEL ?? FALLBACK_MODEL;
export interface DeepSeekEnv {
baseUrl?: string;
model?: string;
}
export async function chat(
messages: ChatMessage[],
apiKey: string,
jsonMode = false,
dsEnv?: DeepSeekEnv
): Promise<string> {
const base = dsEnv?.baseUrl ?? process.env.DEEPSEEK_BASE_URL ?? FALLBACK_BASE;
const model = dsEnv?.model ?? process.env.DEEPSEEK_MODEL ?? FALLBACK_MODEL;
const res = await fetch(`${base}/v1/chat/completions`, {
method: "POST",
headers: {
@@ -64,7 +74,8 @@ Rules:
export async function curate(
apiKey: string,
stats: RepoStats,
feed: FeedItem[]
feed: FeedItem[],
dsEnv?: DeepSeekEnv
): Promise<CuratedDispatch> {
const trimmedFeed = feed.slice(0, 25).map((f) => ({
kind: f.kind,
@@ -96,7 +107,8 @@ export async function curate(
{ role: "user", content: JSON.stringify(userPayload, null, 2) },
],
apiKey,
true
true,
dsEnv
);
const parsed = JSON.parse(raw) as Omit<CuratedDispatch, "generatedAt">;
+3 -8
View File
@@ -18,13 +18,8 @@ export interface RepoFacts {
}
export const FACTS: RepoFacts = {
<<<<<<< Updated upstream
"generatedAt": "2026-05-12T03:14:50.815Z",
"version": "0.8.30",
=======
"generatedAt": "2026-05-10T15:06:44.698Z",
"version": "0.8.27",
>>>>>>> Stashed changes
"generatedAt": "2026-05-12T19:02:49.213Z",
"version": "0.8.32",
"crates": [
"agent",
"app-server",
@@ -95,7 +90,7 @@ export const FACTS: RepoFacts = {
],
"defaultModel": "deepseek-v4-pro",
"nodeEngines": ">=18",
"toolCount": 62,
"toolCount": 64,
"license": "MIT",
"latestRelease": null
};
+4
View File
@@ -16,6 +16,8 @@ interface KVNamespace {
interface CloudflareEnv {
CURATED_KV?: KVNamespace;
DEEPSEEK_API_KEY?: string;
DEEPSEEK_BASE_URL?: string;
DEEPSEEK_MODEL?: string;
GITHUB_TOKEN?: string;
CRON_SECRET?: string;
GITHUB_REPO?: string;
@@ -29,6 +31,8 @@ export async function getEnv(): Promise<CloudflareEnv> {
} catch {
return {
DEEPSEEK_API_KEY: process.env.DEEPSEEK_API_KEY,
DEEPSEEK_BASE_URL: process.env.DEEPSEEK_BASE_URL,
DEEPSEEK_MODEL: process.env.DEEPSEEK_MODEL,
GITHUB_TOKEN: process.env.GITHUB_TOKEN,
CRON_SECRET: process.env.CRON_SECRET,
GITHUB_REPO: process.env.GITHUB_REPO,
+8 -3
View File
@@ -14,10 +14,15 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
const cfgPath = join(__dirname, "..", "wrangler.jsonc");
const raw = readFileSync(cfgPath, "utf-8");
// Parse JSONC (strip comments, trailing commas)
// Parse JSONC (strip comments, trailing commas).
// Use a two-pass approach to avoid mangling URLs: first strip
// line comments that look like comments (preceded by whitespace
// or comma, not part of ://), then strip block comments.
const stripped = raw
.replace(/\/\/.*$/gm, "") // line comments
.replace(/\/\*[\s\S]*?\*\//g, ""); // block comments
.replace(/(^|[,\s])\/\/[^\n]*/gm, "$1") // line comments (skips :// in URLs)
.replace(/\/\*[\s\S]*?\*\//g, "") // block comments
.replace(/,\s*}/g, "}") // trailing commas
.replace(/,\s*]/g, "]");
const cfg = JSON.parse(stripped);
const nss = cfg.kv_namespaces;