mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 06:07:28 +00:00
hooks: add system-context prompt composition coverage
This commit is contained in:
@@ -17,6 +17,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Slack/DM typing feedback: add `channels.slack.typingReaction` so Socket Mode DMs can show reaction-based processing status even when Slack native assistant typing is unavailable. (#19816) Thanks @dalefrieswthat.
|
||||
- Cron/job snapshot persistence: skip backup during normalization persistence in `ensureLoaded` so `jobs.json.bak` keeps the pre-edit snapshot for recovery, while preserving backup creation on explicit user-driven writes. (#35234) Thanks @0xsline.
|
||||
- TTS/OpenAI-compatible endpoints: add `messages.tts.openai.baseUrl` config support with config-over-env precedence, endpoint-aware directive validation, and OpenAI TTS request routing to the resolved base URL. (#34321) thanks @RealKai42.
|
||||
- Plugins/before_prompt_build system-context fields: add `prependSystemContext` and `appendSystemContext` so static plugin guidance can be placed in system prompt space for provider caching and lower repeated prompt token cost. (#35177) thanks @maweibin.
|
||||
|
||||
### Fixes
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ See [Hooks](/automation/hooks) for setup and examples.
|
||||
These run inside the agent loop or gateway pipeline:
|
||||
|
||||
- **`before_model_resolve`**: runs pre-session (no `messages`) to deterministically override provider/model before model resolution.
|
||||
- **`before_prompt_build`**: runs after session load (with `messages`) to inject `prependContext`/`systemPrompt` before prompt submission.
|
||||
- **`before_prompt_build`**: runs after session load (with `messages`) to inject `prependContext`, `systemPrompt`, `prependSystemContext`, or `appendSystemContext` before prompt submission.
|
||||
- **`before_agent_start`**: legacy compatibility hook that may run in either phase; prefer the explicit hooks above.
|
||||
- **`agent_end`**: inspect the final message list and run metadata after completion.
|
||||
- **`before_compaction` / `after_compaction`**: observe or annotate compaction cycles.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../config/config.js";
|
||||
import {
|
||||
composeSystemPromptWithHookContext,
|
||||
isOllamaCompatProvider,
|
||||
resolveAttemptFsWorkspaceOnly,
|
||||
resolveOllamaBaseUrlForRun,
|
||||
@@ -75,6 +76,31 @@ describe("resolvePromptBuildHookResult", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("composeSystemPromptWithHookContext", () => {
|
||||
it("returns undefined when no hook system context is provided", () => {
|
||||
expect(composeSystemPromptWithHookContext({ baseSystemPrompt: "base" })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("builds prepend/base/append system prompt order", () => {
|
||||
expect(
|
||||
composeSystemPromptWithHookContext({
|
||||
baseSystemPrompt: " base system ",
|
||||
prependSystemContext: " prepend ",
|
||||
appendSystemContext: " append ",
|
||||
}),
|
||||
).toBe("prepend\n\nbase system\n\nappend");
|
||||
});
|
||||
|
||||
it("avoids blank separators when base system prompt is empty", () => {
|
||||
expect(
|
||||
composeSystemPromptWithHookContext({
|
||||
baseSystemPrompt: " ",
|
||||
appendSystemContext: " append only ",
|
||||
}),
|
||||
).toBe("append only");
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolvePromptModeForSession", () => {
|
||||
it("uses minimal mode for subagent sessions", () => {
|
||||
expect(resolvePromptModeForSession("agent:main:subagent:child")).toBe("minimal");
|
||||
|
||||
@@ -582,6 +582,22 @@ export async function resolvePromptBuildHookResult(params: {
|
||||
};
|
||||
}
|
||||
|
||||
export function composeSystemPromptWithHookContext(params: {
|
||||
baseSystemPrompt?: string;
|
||||
prependSystemContext?: string;
|
||||
appendSystemContext?: string;
|
||||
}): string | undefined {
|
||||
const prependSystem = params.prependSystemContext?.trim();
|
||||
const appendSystem = params.appendSystemContext?.trim();
|
||||
const baseSystem = params.baseSystemPrompt?.trim() ?? "";
|
||||
if (!prependSystem && !appendSystem) {
|
||||
return undefined;
|
||||
}
|
||||
return [prependSystem, baseSystem, appendSystem]
|
||||
.filter((value): value is string => Boolean(value))
|
||||
.join("\n\n");
|
||||
}
|
||||
|
||||
export function resolvePromptModeForSession(sessionKey?: string): "minimal" | "full" {
|
||||
if (!sessionKey) {
|
||||
return "full";
|
||||
@@ -1531,20 +1547,18 @@ export async function runEmbeddedAttempt(
|
||||
systemPromptText = legacySystemPrompt;
|
||||
log.debug(`hooks: applied systemPrompt override (${legacySystemPrompt.length} chars)`);
|
||||
}
|
||||
const prependSystem = hookResult?.prependSystemContext?.trim();
|
||||
const appendSystem = hookResult?.appendSystemContext?.trim();
|
||||
if (prependSystem || appendSystem) {
|
||||
let base = systemPromptText ?? "";
|
||||
if (prependSystem) {
|
||||
base = `${prependSystem}\n\n${base}`;
|
||||
}
|
||||
if (appendSystem) {
|
||||
base = `${base}\n\n${appendSystem}`;
|
||||
}
|
||||
applySystemPromptOverrideToSession(activeSession, base);
|
||||
systemPromptText = base;
|
||||
const prependedOrAppendedSystemPrompt = composeSystemPromptWithHookContext({
|
||||
baseSystemPrompt: systemPromptText,
|
||||
prependSystemContext: hookResult?.prependSystemContext,
|
||||
appendSystemContext: hookResult?.appendSystemContext,
|
||||
});
|
||||
if (prependedOrAppendedSystemPrompt) {
|
||||
const prependSystemLen = hookResult?.prependSystemContext?.trim().length ?? 0;
|
||||
const appendSystemLen = hookResult?.appendSystemContext?.trim().length ?? 0;
|
||||
applySystemPromptOverrideToSession(activeSession, prependedOrAppendedSystemPrompt);
|
||||
systemPromptText = prependedOrAppendedSystemPrompt;
|
||||
log.debug(
|
||||
`hooks: applied prependSystemContext/appendSystemContext (${prependSystem?.length ?? 0}+${appendSystem?.length ?? 0} chars)`,
|
||||
`hooks: applied prependSystemContext/appendSystemContext (${prependSystemLen}+${appendSystemLen} chars)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user