diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ffcb9648c3..2b6706401fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -128,6 +128,7 @@ Docs: https://docs.openclaw.ai - Control UI/sessions: fire the documented `/new` command and lifecycle hooks only for explicit Control UI session creation, restoring session-memory and custom hook capture without changing SDK parent-session creates. Fixes #76957. Thanks @BunsDev. - Exec approvals: fall back to a guarded copy when Windows rejects rename-overwrite for `exec-approvals.json`, while preserving symlink, hard-link, and owner-only permission safeguards. Fixes #77785. (#77907) Thanks @Alex-Alaniz and @MilleniumGenAI. - Slack: preserve Socket Mode SDK error context and structured Slack API fields in reconnect logs, so startup failures no longer collapse to a bare `unknown error`. +- Agents/subagents: preserve the delegated task prompt when a spawned target agent uses `systemPromptOverride`, so `sessions_spawn(mode: "run")` child runs still see their assigned task. Fixes #77950. Thanks @amknight. - iOS pairing: allow setup-code and manual `ws://` connects for private LAN and `.local` gateways while keeping Tailscale/public routes on `wss://`, and prefer explicit gateway passwords over stale bootstrap tokens in mixed-auth reconnects. Fixes #47887; carries forward #65185. Thanks @draix and @BunsDev. - Node/Windows: fall back to the Startup-folder launcher when Spanish-localized `schtasks` reports `Acceso denegado`, matching the existing access-denied fallback path. Fixes #77993. Thanks @jackonedev. - Plugins/diagnostics: make source-only TypeScript package warnings actionable by explaining that missing compiled runtime output is a publisher packaging issue and pointing users to update/reinstall or disable/uninstall the plugin. Fixes #77835. Thanks @googlerest. diff --git a/src/agents/pi-embedded-runner/run/attempt-system-prompt.test.ts b/src/agents/pi-embedded-runner/run/attempt-system-prompt.test.ts index 1bf4ee41155..a77721eaea4 100644 --- a/src/agents/pi-embedded-runner/run/attempt-system-prompt.test.ts +++ b/src/agents/pi-embedded-runner/run/attempt-system-prompt.test.ts @@ -68,6 +68,38 @@ describe("buildAttemptSystemPrompt", () => { expect(result.systemPrompt).not.toContain("USER.md"); }); + it("preserves runtime extra system prompt context when a system prompt override is configured", () => { + const result = buildAttemptSystemPrompt({ + isRawModelRun: false, + systemPromptOverrideText: "Custom override prompt.", + transformProviderSystemPrompt, + embeddedSystemPrompt: { + workspaceDir: "/tmp/openclaw", + reasoningTagHint: false, + runtimeInfo: { + host: "test-host", + os: "Darwin", + arch: "arm64", + node: "v22.0.0", + model: "openai/gpt-5.5", + }, + tools: [], + modelAliasLines: [], + userTimezone: "UTC", + promptMode: "minimal", + extraSystemPrompt: + "# Subagent Context\n\n## Your Role\n- You were created to handle: RUN_MODE_TASK_77950", + bootstrapMode: "full", + contextFiles: [], + }, + providerTransform: baseProviderTransform, + }); + + expect(result.systemPrompt).toContain("Custom override prompt."); + expect(result.systemPrompt).toContain("## Subagent Context"); + expect(result.systemPrompt).toContain("RUN_MODE_TASK_77950"); + }); + it("omits system prompts for raw model probes", () => { const result = buildAttemptSystemPrompt({ isRawModelRun: true, diff --git a/src/agents/pi-embedded-runner/run/attempt-system-prompt.ts b/src/agents/pi-embedded-runner/run/attempt-system-prompt.ts index 41c33f7b633..9398e5f2478 100644 --- a/src/agents/pi-embedded-runner/run/attempt-system-prompt.ts +++ b/src/agents/pi-embedded-runner/run/attempt-system-prompt.ts @@ -30,15 +30,33 @@ export type AttemptSystemPrompt = { systemPromptOverride: (defaultPrompt?: string) => string; }; +function appendRuntimeExtraSystemPrompt(params: { + systemPrompt: string; + extraSystemPrompt?: string; + promptMode?: EmbeddedSystemPromptParams["promptMode"]; +}): string { + const extraSystemPrompt = params.extraSystemPrompt?.trim(); + if (!extraSystemPrompt || params.promptMode === "none") { + return params.systemPrompt; + } + const contextHeader = + params.promptMode === "minimal" ? "## Subagent Context" : "## Group Chat Context"; + return `${params.systemPrompt.trimEnd()}\n\n${contextHeader}\n${extraSystemPrompt}\n`; +} + export function buildAttemptSystemPrompt( params: BuildAttemptSystemPromptParams, ): AttemptSystemPrompt { const baseSystemPrompt = params.systemPromptOverrideText - ? appendAgentBootstrapSystemPromptSupplement({ - systemPrompt: params.systemPromptOverrideText, - bootstrapMode: params.embeddedSystemPrompt.bootstrapMode, - bootstrapTruncationNotice: params.embeddedSystemPrompt.bootstrapTruncationNotice, - contextFiles: params.embeddedSystemPrompt.contextFiles, + ? appendRuntimeExtraSystemPrompt({ + systemPrompt: appendAgentBootstrapSystemPromptSupplement({ + systemPrompt: params.systemPromptOverrideText, + bootstrapMode: params.embeddedSystemPrompt.bootstrapMode, + bootstrapTruncationNotice: params.embeddedSystemPrompt.bootstrapTruncationNotice, + contextFiles: params.embeddedSystemPrompt.contextFiles, + }), + extraSystemPrompt: params.embeddedSystemPrompt.extraSystemPrompt, + promptMode: params.embeddedSystemPrompt.promptMode, }) : buildEmbeddedSystemPrompt(params.embeddedSystemPrompt);