feat(agent): layered system prompt, environment facts and intent-routed skills
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
0f20c19b7c
commit
21b7e8ff23
25 files changed
+1783
-149
No files matched your search
@@ -0,0 +1,113 @@
|
||||
import {
|
||||
accountName,
|
||||
downloadStatusName,
|
||||
healthName,
|
||||
humanNow,
|
||||
humanRelative,
|
||||
kindName,
|
||||
subscriptionStatusName,
|
||||
} from "../format.ts";
|
||||
import type { EnvironmentFacts, PromptSection } from "../types.ts";
|
||||
|
||||
// 第 2 层:环境事实。会话开始时服务端从业务表读出的摘要,让模型知道"有什么"再去查"怎么样":
|
||||
// 反例(docs/design/agent-report-sample-bad.md)里模型只看了站点列表,就汇报"系统里没有下载器"。
|
||||
// 只写名称、类型、状态和计数,不写地址、ID 与凭证;数字以会话开始时为准,细节仍以工具结果为准。
|
||||
|
||||
const MAX_NAMED = 6;
|
||||
|
||||
function names<T>(items: readonly T[], render: (x: T) => string): string {
|
||||
const shown = items.slice(0, MAX_NAMED).map(render);
|
||||
const more = items.length - shown.length;
|
||||
return more > 0 ? `${shown.join(";")};另有 ${more} 个` : shown.join(";");
|
||||
}
|
||||
|
||||
/** 计数表 → "追更中 3、已取消 2";全 0 返回空串 */
|
||||
function counts(m: Record<string, number>, label: (k: string) => string): string {
|
||||
return Object.entries(m)
|
||||
.filter(([, n]) => n > 0)
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.map(([k, n]) => `${label(k)} ${n}`)
|
||||
.join("、");
|
||||
}
|
||||
|
||||
const total = (m: Record<string, number>) => Object.values(m).reduce((a, b) => a + b, 0);
|
||||
|
||||
export function renderEnvironment(f: EnvironmentFacts): string[] {
|
||||
const now = new Date(f.now);
|
||||
const tz = f.timeZone;
|
||||
const rel = (iso: string | null) => humanRelative(iso, now, tz);
|
||||
const lines: string[] = [`现在:${humanNow(now, tz)}。`];
|
||||
|
||||
const dl = f.downloaders.filter((d) => d.enabled);
|
||||
if (dl.length === 0)
|
||||
lines.push(
|
||||
f.downloaders.length > 0
|
||||
? `下载器:${f.downloaders.length} 个都已停用。`
|
||||
: "下载器:还没有接入(设置 → 下载器)。",
|
||||
);
|
||||
else
|
||||
lines.push(
|
||||
`下载器 ${dl.length} 个:${names(dl, (d) => {
|
||||
const seen = rel(d.lastSeenAt);
|
||||
const t = d.tasks;
|
||||
const tasks =
|
||||
t.total > 0
|
||||
? `,本工具管理 ${t.total} 个任务(进行中 ${t.active}、失败 ${t.failed})`
|
||||
: ",没有本工具管理的任务";
|
||||
return `「${d.name}」${kindName(d.kind)},${healthName(d.health)}${seen ? `(${seen})` : ""}${tasks}`;
|
||||
})}。`,
|
||||
);
|
||||
|
||||
const ms = f.mediaServers.filter((m) => m.enabled);
|
||||
lines.push(
|
||||
ms.length === 0
|
||||
? "媒体服务器:还没有接入。"
|
||||
: `媒体服务器 ${ms.length} 个:${names(ms, (m) => {
|
||||
const seen = rel(m.lastSeenAt);
|
||||
return `「${m.name}」${kindName(m.kind)},${healthName(m.health)}${seen ? `(${seen})` : ""}`;
|
||||
})}。`,
|
||||
);
|
||||
|
||||
const sites = f.sites.filter((s) => s.enabled);
|
||||
lines.push(
|
||||
sites.length === 0
|
||||
? "站点:还没有启用的站点。"
|
||||
: `站点 ${sites.length} 个:${names(sites, (s) => {
|
||||
const at = rel(s.lastHealthAt);
|
||||
const health =
|
||||
s.health === "unknown" ? "还没检查过" : `上次检查${healthName(s.health)}${at ? `(${at})` : ""}`;
|
||||
return `「${s.name}」${kindName(s.kind)},${health}${s.account ? `,${accountName(s.account)}` : ""}`;
|
||||
})}。`,
|
||||
);
|
||||
|
||||
const roots = f.libraryRoots.filter((r) => r.enabled);
|
||||
lines.push(
|
||||
roots.length === 0
|
||||
? "媒体库目录:还没有登记。"
|
||||
: `媒体库目录 ${roots.length} 个:${names(roots, (r) => `「${r.name}」${healthName(r.health)}`)}。`,
|
||||
);
|
||||
|
||||
const subs = total(f.subscriptions);
|
||||
lines.push(subs === 0 ? "订阅:没有。" : `订阅 ${subs} 个:${counts(f.subscriptions, subscriptionStatusName)}。`);
|
||||
const dls = total(f.downloads);
|
||||
lines.push(
|
||||
dls === 0
|
||||
? "下载任务(本工具管理):没有。"
|
||||
: `下载任务(本工具管理)${dls} 个:${counts(f.downloads, downloadStatusName)}。`,
|
||||
);
|
||||
lines.push(f.openDecisions === 0 ? "待处理事项:没有。" : `待处理事项:${f.openDecisions} 条未关闭。`);
|
||||
if (f.webSearch !== undefined) lines.push(f.webSearch ? "网页搜索:已开启。" : "网页搜索:未开启。");
|
||||
return lines;
|
||||
}
|
||||
|
||||
export function environmentLayer(f: EnvironmentFacts | null | undefined): PromptSection {
|
||||
if (!f) return { layer: "environment", title: "当前环境", lines: [] };
|
||||
return {
|
||||
layer: "environment",
|
||||
title: "当前环境",
|
||||
lines: [
|
||||
"会话开始时的快照,只有名称、状态和计数;要细节或最新状态用下面的能力查。这里写了「还没有接入」的就是真的没有,不用再向用户确认。",
|
||||
...renderEnvironment(f).map((l) => `- ${l}`),
|
||||
],
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user