Add files using upload-large-folder tool
Browse files
src/auto-reply/reply/commands-context-report.test.ts
CHANGED
|
@@ -32,6 +32,15 @@ function makeParams(
|
|
| 32 |
bootstrapMaxChars: options?.omitBootstrapLimits ? undefined : 20_000,
|
| 33 |
bootstrapTotalMaxChars: options?.omitBootstrapLimits ? undefined : 150_000,
|
| 34 |
sandbox: { mode: "off", sandboxed: false },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
systemPrompt: {
|
| 36 |
chars: 1_000,
|
| 37 |
projectContextChars: 500,
|
|
@@ -89,4 +98,11 @@ describe("buildContextReply", () => {
|
|
| 89 |
expect(result.text).toContain("Bootstrap max/total: 150,000 chars");
|
| 90 |
expect(result.text).not.toContain("Bootstrap max/file: ? chars");
|
| 91 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
});
|
|
|
|
| 32 |
bootstrapMaxChars: options?.omitBootstrapLimits ? undefined : 20_000,
|
| 33 |
bootstrapTotalMaxChars: options?.omitBootstrapLimits ? undefined : 150_000,
|
| 34 |
sandbox: { mode: "off", sandboxed: false },
|
| 35 |
+
preparation: {
|
| 36 |
+
totalMs: 123,
|
| 37 |
+
skillsMs: 11,
|
| 38 |
+
bootstrapMs: 22,
|
| 39 |
+
toolsMs: 33,
|
| 40 |
+
runtimeInfoMs: 4,
|
| 41 |
+
docsPathMs: 5,
|
| 42 |
+
systemPromptBuildMs: 6,
|
| 43 |
+
},
|
| 44 |
systemPrompt: {
|
| 45 |
chars: 1_000,
|
| 46 |
projectContextChars: 500,
|
|
|
|
| 98 |
expect(result.text).toContain("Bootstrap max/total: 150,000 chars");
|
| 99 |
expect(result.text).not.toContain("Bootstrap max/file: ? chars");
|
| 100 |
});
|
| 101 |
+
|
| 102 |
+
it("shows prompt preparation timings in detail mode when available", async () => {
|
| 103 |
+
const result = await buildContextReply(makeParams("/context detail", false));
|
| 104 |
+
expect(result.text).toContain("Prompt prep total: 123 ms");
|
| 105 |
+
expect(result.text).toContain("- bootstrap/context: 22 ms");
|
| 106 |
+
expect(result.text).toContain("- system prompt build: 6 ms");
|
| 107 |
+
});
|
| 108 |
});
|
src/auto-reply/reply/commands-context-report.ts
CHANGED
|
@@ -21,6 +21,10 @@ function formatCharsAndTokens(chars: number): string {
|
|
| 21 |
return `${formatInt(chars)} chars (~${formatInt(estimateTokensFromChars(chars))} tok)`;
|
| 22 |
}
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
function parseContextArgs(commandBodyNormalized: string): string {
|
| 25 |
if (commandBodyNormalized === "/context") {
|
| 26 |
return "";
|
|
@@ -52,8 +56,15 @@ async function resolveContextReport(
|
|
| 52 |
|
| 53 |
const bootstrapMaxChars = resolveBootstrapMaxChars(params.cfg);
|
| 54 |
const bootstrapTotalMaxChars = resolveBootstrapTotalMaxChars(params.cfg);
|
| 55 |
-
const {
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
return buildSystemPromptReport({
|
| 59 |
source: "estimate",
|
|
@@ -66,6 +77,7 @@ async function resolveContextReport(
|
|
| 66 |
bootstrapMaxChars,
|
| 67 |
bootstrapTotalMaxChars,
|
| 68 |
sandbox: { mode: sandboxRuntime.mode, sandboxed: sandboxRuntime.sandboxed },
|
|
|
|
| 69 |
systemPrompt,
|
| 70 |
bootstrapFiles,
|
| 71 |
injectedFiles,
|
|
@@ -141,6 +153,18 @@ export async function buildContextReply(params: HandleCommandsParams): Promise<R
|
|
| 141 |
? `Tools: ${formatNameList(toolNames, 30)}`
|
| 142 |
: "Tools: (none)";
|
| 143 |
const systemPromptLine = `System prompt (${report.source}): ${formatCharsAndTokens(report.systemPrompt.chars)} (Project Context ${formatCharsAndTokens(report.systemPrompt.projectContextChars)})`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
const workspaceLabel = report.workspaceDir ?? params.workspaceDir;
|
| 145 |
const bootstrapMaxChars =
|
| 146 |
typeof report.bootstrapMaxChars === "number" &&
|
|
@@ -200,6 +224,7 @@ export async function buildContextReply(params: HandleCommandsParams): Promise<R
|
|
| 200 |
`Bootstrap max/total: ${bootstrapTotalLabel}`,
|
| 201 |
sandboxLine,
|
| 202 |
systemPromptLine,
|
|
|
|
| 203 |
...(bootstrapWarningLines.length ? ["", ...bootstrapWarningLines] : []),
|
| 204 |
"",
|
| 205 |
"Injected workspace files:",
|
|
|
|
| 21 |
return `${formatInt(chars)} chars (~${formatInt(estimateTokensFromChars(chars))} tok)`;
|
| 22 |
}
|
| 23 |
|
| 24 |
+
function formatDurationMs(ms: number): string {
|
| 25 |
+
return `${formatInt(ms)} ms`;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
function parseContextArgs(commandBodyNormalized: string): string {
|
| 29 |
if (commandBodyNormalized === "/context") {
|
| 30 |
return "";
|
|
|
|
| 56 |
|
| 57 |
const bootstrapMaxChars = resolveBootstrapMaxChars(params.cfg);
|
| 58 |
const bootstrapTotalMaxChars = resolveBootstrapTotalMaxChars(params.cfg);
|
| 59 |
+
const {
|
| 60 |
+
systemPrompt,
|
| 61 |
+
tools,
|
| 62 |
+
skillsPrompt,
|
| 63 |
+
bootstrapFiles,
|
| 64 |
+
injectedFiles,
|
| 65 |
+
sandboxRuntime,
|
| 66 |
+
preparation,
|
| 67 |
+
} = await resolveCommandsSystemPromptBundle(params);
|
| 68 |
|
| 69 |
return buildSystemPromptReport({
|
| 70 |
source: "estimate",
|
|
|
|
| 77 |
bootstrapMaxChars,
|
| 78 |
bootstrapTotalMaxChars,
|
| 79 |
sandbox: { mode: sandboxRuntime.mode, sandboxed: sandboxRuntime.sandboxed },
|
| 80 |
+
preparation,
|
| 81 |
systemPrompt,
|
| 82 |
bootstrapFiles,
|
| 83 |
injectedFiles,
|
|
|
|
| 153 |
? `Tools: ${formatNameList(toolNames, 30)}`
|
| 154 |
: "Tools: (none)";
|
| 155 |
const systemPromptLine = `System prompt (${report.source}): ${formatCharsAndTokens(report.systemPrompt.chars)} (Project Context ${formatCharsAndTokens(report.systemPrompt.projectContextChars)})`;
|
| 156 |
+
const preparation = report.preparation;
|
| 157 |
+
const prepLines = preparation
|
| 158 |
+
? [
|
| 159 |
+
`Prompt prep total: ${formatDurationMs(preparation.totalMs)}`,
|
| 160 |
+
`- skills: ${formatDurationMs(preparation.skillsMs ?? 0)}`,
|
| 161 |
+
`- bootstrap/context: ${formatDurationMs(preparation.bootstrapMs ?? 0)}`,
|
| 162 |
+
`- tools: ${formatDurationMs(preparation.toolsMs ?? 0)}`,
|
| 163 |
+
`- runtime info: ${formatDurationMs(preparation.runtimeInfoMs ?? 0)}`,
|
| 164 |
+
`- docs path: ${formatDurationMs(preparation.docsPathMs ?? 0)}`,
|
| 165 |
+
`- system prompt build: ${formatDurationMs(preparation.systemPromptBuildMs ?? 0)}`,
|
| 166 |
+
]
|
| 167 |
+
: [];
|
| 168 |
const workspaceLabel = report.workspaceDir ?? params.workspaceDir;
|
| 169 |
const bootstrapMaxChars =
|
| 170 |
typeof report.bootstrapMaxChars === "number" &&
|
|
|
|
| 224 |
`Bootstrap max/total: ${bootstrapTotalLabel}`,
|
| 225 |
sandboxLine,
|
| 226 |
systemPromptLine,
|
| 227 |
+
...(prepLines.length ? ["", ...prepLines] : []),
|
| 228 |
...(bootstrapWarningLines.length ? ["", ...bootstrapWarningLines] : []),
|
| 229 |
"",
|
| 230 |
"Injected workspace files:",
|
src/auto-reply/reply/commands-system-prompt.ts
CHANGED
|
@@ -22,18 +22,30 @@ export type CommandsSystemPromptBundle = {
|
|
| 22 |
bootstrapFiles: WorkspaceBootstrapFile[];
|
| 23 |
injectedFiles: EmbeddedContextFile[];
|
| 24 |
sandboxRuntime: ReturnType<typeof resolveSandboxRuntimeStatus>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
};
|
| 26 |
|
| 27 |
export async function resolveCommandsSystemPromptBundle(
|
| 28 |
params: HandleCommandsParams,
|
| 29 |
): Promise<CommandsSystemPromptBundle> {
|
| 30 |
const workspaceDir = params.workspaceDir;
|
|
|
|
|
|
|
| 31 |
const { bootstrapFiles, contextFiles: injectedFiles } = await resolveBootstrapContextForRun({
|
| 32 |
workspaceDir,
|
| 33 |
config: params.cfg,
|
| 34 |
sessionKey: params.sessionKey,
|
| 35 |
sessionId: params.sessionEntry?.sessionId,
|
| 36 |
});
|
|
|
|
|
|
|
| 37 |
const skillsSnapshot = (() => {
|
| 38 |
try {
|
| 39 |
return buildWorkspaceSkillSnapshot(workspaceDir, {
|
|
@@ -45,11 +57,13 @@ export async function resolveCommandsSystemPromptBundle(
|
|
| 45 |
return { prompt: "", skills: [], resolvedSkills: [] };
|
| 46 |
}
|
| 47 |
})();
|
|
|
|
| 48 |
const skillsPrompt = skillsSnapshot.prompt ?? "";
|
| 49 |
const sandboxRuntime = resolveSandboxRuntimeStatus({
|
| 50 |
cfg: params.cfg,
|
| 51 |
sessionKey: params.ctx.SessionKey ?? params.sessionKey,
|
| 52 |
});
|
|
|
|
| 53 |
const tools = (() => {
|
| 54 |
try {
|
| 55 |
return createOpenClawCodingTools({
|
|
@@ -70,6 +84,7 @@ export async function resolveCommandsSystemPromptBundle(
|
|
| 70 |
return [];
|
| 71 |
}
|
| 72 |
})();
|
|
|
|
| 73 |
const toolSummaries = buildToolSummaryMap(tools);
|
| 74 |
const toolNames = tools.map((t) => t.name);
|
| 75 |
const { sessionAgentId } = resolveSessionAgentIds({
|
|
@@ -82,6 +97,7 @@ export async function resolveCommandsSystemPromptBundle(
|
|
| 82 |
agentId: sessionAgentId,
|
| 83 |
});
|
| 84 |
const defaultModelLabel = `${defaultModelRef.provider}/${defaultModelRef.model}`;
|
|
|
|
| 85 |
const { runtimeInfo, userTimezone, userTime, userTimeFormat } = buildSystemPromptParams({
|
| 86 |
config: params.cfg,
|
| 87 |
agentId: sessionAgentId,
|
|
@@ -96,6 +112,7 @@ export async function resolveCommandsSystemPromptBundle(
|
|
| 96 |
defaultModel: defaultModelLabel,
|
| 97 |
},
|
| 98 |
});
|
|
|
|
| 99 |
const sandboxInfo = sandboxRuntime.sandboxed
|
| 100 |
? {
|
| 101 |
enabled: true,
|
|
@@ -109,6 +126,7 @@ export async function resolveCommandsSystemPromptBundle(
|
|
| 109 |
: { enabled: false };
|
| 110 |
const ttsHint = params.cfg ? buildTtsSystemPromptHint(params.cfg) : undefined;
|
| 111 |
|
|
|
|
| 112 |
const systemPrompt = buildAgentSystemPrompt({
|
| 113 |
workspaceDir,
|
| 114 |
defaultThinkLevel: params.resolvedThinkLevel,
|
|
@@ -131,6 +149,22 @@ export async function resolveCommandsSystemPromptBundle(
|
|
| 131 |
sandboxInfo,
|
| 132 |
memoryCitationsMode: params.cfg?.memory?.citations,
|
| 133 |
});
|
|
|
|
| 134 |
|
| 135 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
}
|
|
|
|
| 22 |
bootstrapFiles: WorkspaceBootstrapFile[];
|
| 23 |
injectedFiles: EmbeddedContextFile[];
|
| 24 |
sandboxRuntime: ReturnType<typeof resolveSandboxRuntimeStatus>;
|
| 25 |
+
preparation: {
|
| 26 |
+
totalMs: number;
|
| 27 |
+
skillsMs?: number;
|
| 28 |
+
bootstrapMs?: number;
|
| 29 |
+
toolsMs?: number;
|
| 30 |
+
runtimeInfoMs?: number;
|
| 31 |
+
systemPromptBuildMs?: number;
|
| 32 |
+
};
|
| 33 |
};
|
| 34 |
|
| 35 |
export async function resolveCommandsSystemPromptBundle(
|
| 36 |
params: HandleCommandsParams,
|
| 37 |
): Promise<CommandsSystemPromptBundle> {
|
| 38 |
const workspaceDir = params.workspaceDir;
|
| 39 |
+
const preparationStartedAt = Date.now();
|
| 40 |
+
const bootstrapStartedAt = Date.now();
|
| 41 |
const { bootstrapFiles, contextFiles: injectedFiles } = await resolveBootstrapContextForRun({
|
| 42 |
workspaceDir,
|
| 43 |
config: params.cfg,
|
| 44 |
sessionKey: params.sessionKey,
|
| 45 |
sessionId: params.sessionEntry?.sessionId,
|
| 46 |
});
|
| 47 |
+
const bootstrapMs = Date.now() - bootstrapStartedAt;
|
| 48 |
+
const skillsStartedAt = Date.now();
|
| 49 |
const skillsSnapshot = (() => {
|
| 50 |
try {
|
| 51 |
return buildWorkspaceSkillSnapshot(workspaceDir, {
|
|
|
|
| 57 |
return { prompt: "", skills: [], resolvedSkills: [] };
|
| 58 |
}
|
| 59 |
})();
|
| 60 |
+
const skillsMs = Date.now() - skillsStartedAt;
|
| 61 |
const skillsPrompt = skillsSnapshot.prompt ?? "";
|
| 62 |
const sandboxRuntime = resolveSandboxRuntimeStatus({
|
| 63 |
cfg: params.cfg,
|
| 64 |
sessionKey: params.ctx.SessionKey ?? params.sessionKey,
|
| 65 |
});
|
| 66 |
+
const toolsStartedAt = Date.now();
|
| 67 |
const tools = (() => {
|
| 68 |
try {
|
| 69 |
return createOpenClawCodingTools({
|
|
|
|
| 84 |
return [];
|
| 85 |
}
|
| 86 |
})();
|
| 87 |
+
const toolsMs = Date.now() - toolsStartedAt;
|
| 88 |
const toolSummaries = buildToolSummaryMap(tools);
|
| 89 |
const toolNames = tools.map((t) => t.name);
|
| 90 |
const { sessionAgentId } = resolveSessionAgentIds({
|
|
|
|
| 97 |
agentId: sessionAgentId,
|
| 98 |
});
|
| 99 |
const defaultModelLabel = `${defaultModelRef.provider}/${defaultModelRef.model}`;
|
| 100 |
+
const runtimeInfoStartedAt = Date.now();
|
| 101 |
const { runtimeInfo, userTimezone, userTime, userTimeFormat } = buildSystemPromptParams({
|
| 102 |
config: params.cfg,
|
| 103 |
agentId: sessionAgentId,
|
|
|
|
| 112 |
defaultModel: defaultModelLabel,
|
| 113 |
},
|
| 114 |
});
|
| 115 |
+
const runtimeInfoMs = Date.now() - runtimeInfoStartedAt;
|
| 116 |
const sandboxInfo = sandboxRuntime.sandboxed
|
| 117 |
? {
|
| 118 |
enabled: true,
|
|
|
|
| 126 |
: { enabled: false };
|
| 127 |
const ttsHint = params.cfg ? buildTtsSystemPromptHint(params.cfg) : undefined;
|
| 128 |
|
| 129 |
+
const systemPromptBuildStartedAt = Date.now();
|
| 130 |
const systemPrompt = buildAgentSystemPrompt({
|
| 131 |
workspaceDir,
|
| 132 |
defaultThinkLevel: params.resolvedThinkLevel,
|
|
|
|
| 149 |
sandboxInfo,
|
| 150 |
memoryCitationsMode: params.cfg?.memory?.citations,
|
| 151 |
});
|
| 152 |
+
const systemPromptBuildMs = Date.now() - systemPromptBuildStartedAt;
|
| 153 |
|
| 154 |
+
return {
|
| 155 |
+
systemPrompt,
|
| 156 |
+
tools,
|
| 157 |
+
skillsPrompt,
|
| 158 |
+
bootstrapFiles,
|
| 159 |
+
injectedFiles,
|
| 160 |
+
sandboxRuntime,
|
| 161 |
+
preparation: {
|
| 162 |
+
totalMs: Date.now() - preparationStartedAt,
|
| 163 |
+
skillsMs,
|
| 164 |
+
bootstrapMs,
|
| 165 |
+
toolsMs,
|
| 166 |
+
runtimeInfoMs,
|
| 167 |
+
systemPromptBuildMs,
|
| 168 |
+
},
|
| 169 |
+
};
|
| 170 |
}
|