


























@@ -4,20 +4,21 @@ import { buildBootstrapInjectionStats } from "./bootstrap-budget.js";
44import type { EmbeddedContextFile } from "./pi-embedded-helpers.js";
55import type { WorkspaceBootstrapFile } from "./workspace.js";
667-function extractBetween(
8-input: string,
9-startMarker: string,
10-endMarker: string,
11-): { text: string; found: boolean } {
7+type ToolReportEntry = SessionSystemPromptReport["tools"]["entries"][number];
8+9+const toolReportEntryCache = new WeakMap<AgentTool, ToolReportEntry>();
10+const toolSchemaStatsCache = new WeakMap<
11+object,
12+Pick<ToolReportEntry, "propertiesCount" | "schemaChars">
13+>();
14+15+function extractBetween(input: string, startMarker: string, endMarker: string): string {
1216const start = input.indexOf(startMarker);
1317if (start === -1) {
14-return { text: "", found: false };
18+return "";
1519}
1620const end = input.indexOf(endMarker, start + startMarker.length);
17-if (end === -1) {
18-return { text: input.slice(start), found: true };
19-}
20-return { text: input.slice(start, end), found: true };
21+return end === -1 ? input.slice(start) : input.slice(start, end);
2122}
22232324function parseSkillBlocks(skillsPrompt: string): Array<{ name: string; blockChars: number }> {
@@ -36,36 +37,57 @@ function parseSkillBlocks(skillsPrompt: string): Array<{ name: string; blockChar
3637.filter((b) => b.blockChars > 0);
3738}
383939-function buildToolsEntries(tools: AgentTool[]): SessionSystemPromptReport["tools"]["entries"] {
40-return tools.map((tool) => {
41-const name = tool.name;
42-const summary = tool.description?.trim() || tool.label?.trim() || "";
43-const summaryChars = summary.length;
44-const schemaChars = (() => {
45-if (!tool.parameters || typeof tool.parameters !== "object") {
46-return 0;
47-}
40+function buildToolSchemaStats(
41+parameters: AgentTool["parameters"],
42+): Pick<ToolReportEntry, "propertiesCount" | "schemaChars"> {
43+if (!parameters || typeof parameters !== "object") {
44+return { schemaChars: 0, propertiesCount: null };
45+}
46+const cached = toolSchemaStatsCache.get(parameters);
47+if (cached) {
48+return cached;
49+}
50+const stats = {
51+schemaChars: (() => {
4852try {
49-return JSON.stringify(tool.parameters).length;
53+return JSON.stringify(parameters).length;
5054} catch {
5155return 0;
5256}
53-})();
54-const propertiesCount = (() => {
55-const schema =
56-tool.parameters && typeof tool.parameters === "object"
57- ? (tool.parameters as Record<string, unknown>)
58- : null;
59-const props = schema && typeof schema.properties === "object" ? schema.properties : null;
57+})(),
58+propertiesCount: (() => {
59+const schema = parameters as Record<string, unknown>;
60+const props = typeof schema.properties === "object" ? schema.properties : null;
6061if (!props || typeof props !== "object") {
6162return null;
6263}
6364return Object.keys(props as Record<string, unknown>).length;
64-})();
65-return { name, summaryChars, schemaChars, propertiesCount };
65+})(),
66+};
67+toolSchemaStatsCache.set(parameters, stats);
68+return stats;
69+}
70+71+function buildToolsEntries(tools: AgentTool[]): SessionSystemPromptReport["tools"]["entries"] {
72+return tools.map((tool) => {
73+const cached = toolReportEntryCache.get(tool);
74+if (cached) {
75+return cached;
76+}
77+const name = tool.name;
78+const summary = tool.description?.trim() || tool.label?.trim() || "";
79+const summaryChars = summary.length;
80+const schemaStats = buildToolSchemaStats(tool.parameters);
81+const entry = { name, summaryChars, ...schemaStats };
82+toolReportEntryCache.set(tool, entry);
83+return entry;
6684});
6785}
688687+function measureRenderedProjectContextChars(systemPrompt: string): number {
88+return extractBetween(systemPrompt, "\n# Project Context\n", "\n## Silent Replies\n").length;
89+}
90+6991export function buildSystemPromptReport(params: {
7092source: SessionSystemPromptReport["source"];
7193generatedAt: number;
@@ -84,13 +106,8 @@ export function buildSystemPromptReport(params: {
84106skillsPrompt: string;
85107tools: AgentTool[];
86108}): SessionSystemPromptReport {
87-const systemPrompt = params.systemPrompt.trim();
88-const projectContext = extractBetween(
89-systemPrompt,
90-"\n# Project Context\n",
91-"\n## Silent Replies\n",
92-);
93-const projectContextChars = projectContext.text.length;
109+const systemPromptChars = params.systemPrompt.length;
110+const projectContextChars = measureRenderedProjectContextChars(params.systemPrompt);
94111const toolsEntries = buildToolsEntries(params.tools);
95112const toolsSchemaChars = toolsEntries.reduce((sum, t) => sum + (t.schemaChars ?? 0), 0);
96113const skillsEntries = parseSkillBlocks(params.skillsPrompt);
@@ -108,9 +125,9 @@ export function buildSystemPromptReport(params: {
108125 ...(params.bootstrapTruncation ? { bootstrapTruncation: params.bootstrapTruncation } : {}),
109126sandbox: params.sandbox,
110127systemPrompt: {
111-chars: systemPrompt.length,
128+chars: systemPromptChars,
112129 projectContextChars,
113-nonProjectContextChars: Math.max(0, systemPrompt.length - projectContextChars),
130+nonProjectContextChars: Math.max(0, systemPromptChars - projectContextChars),
114131},
115132injectedWorkspaceFiles: buildBootstrapInjectionStats({
116133bootstrapFiles: params.bootstrapFiles,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。