fix(agent): keep session scout notices live
This commit is contained in:
@@ -40,7 +40,7 @@
|
||||
- Fixed the vibe pre-init-kill test racing `registry.kill()` against the worker's job-body dispatch (the mock only registered its AgentRef after the abort signal landed, so a loaded runner could observe no registration); the test now waits for the worker to be mid-initialization before killing.
|
||||
### Fixed
|
||||
|
||||
- Removed hard-coded `scout` references from system and tool prompts that leaked into the model even when the scout agent was disabled (`task.disabledAgents`) or absent from the spawn list: the task tool description, delegation gates, plan-mode and workflowz notices, and the glob/grep/ast-grep guidance now only mention scout when it is actually spawnable ([#7313](https://github.com/can1357/oh-my-pi/issues/7313)).
|
||||
- Removed hard-coded `scout` references from agent, system, and tool prompts that leaked into the model even when the scout agent was disabled (`task.disabledAgents`) or absent from the spawn list: the init agent prompt, task tool description, delegation gates, plan-mode and workflowz notices, and glob/grep/ast-grep guidance no longer recommend an unavailable agent, including after live settings changes ([#7313](https://github.com/can1357/oh-my-pi/issues/7313)).
|
||||
|
||||
## [17.2.4] - 2026-08-01
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Generate AGENTS.md for current codebase
|
||||
thinking-level: medium
|
||||
---
|
||||
|
||||
Generate AGENTS.md by launching multiple `scout` agents in parallel (via `task` tool) scanning different areas (core src, tests, configs/build, scripts/docs), then synthesize findings into a single file.
|
||||
Generate AGENTS.md by launching multiple research agents in parallel (via `task` tool) to scan different areas (core src, tests, configs/build, scripts/docs), then synthesize findings into a single file.
|
||||
|
||||
<structure>
|
||||
- **Project Overview**: Brief description of project purpose
|
||||
|
||||
@@ -3347,10 +3347,7 @@ async function createAgentSessionScoped(options: CreateAgentSessionOptions): Pro
|
||||
initialAdvisorCosts,
|
||||
settings,
|
||||
autoApprove: options.autoApprove,
|
||||
scoutAvailable: isScoutSpawnable(
|
||||
settings.get("task.disabledAgents") as string[] | undefined,
|
||||
options.spawns ?? "*",
|
||||
),
|
||||
scoutAllowedBySpawnPolicy: isScoutSpawnable(undefined, options.spawns ?? "*"),
|
||||
evalKernelOwnerId,
|
||||
// Defined only for top-level sessions (creation is gated above).
|
||||
// AgentSession uses this to decide whether it may dispose the global
|
||||
|
||||
@@ -109,8 +109,8 @@ export interface AgentSessionConfig {
|
||||
agent: Agent;
|
||||
sessionManager: SessionManager;
|
||||
settings: Settings;
|
||||
/** Whether the read-only `scout` subagent is spawnable (not disabled, allowed by spawn policy). Defaults to true. */
|
||||
scoutAvailable?: boolean;
|
||||
/** Whether the session spawn policy permits the read-only `scout` subagent. Defaults to true. */
|
||||
scoutAllowedBySpawnPolicy?: boolean;
|
||||
/** Whether the caller explicitly requested yolo/auto-approve behavior for this session. */
|
||||
autoApprove?: boolean;
|
||||
/** Models to cycle through with Ctrl+P (from --models flag). */
|
||||
|
||||
@@ -518,7 +518,7 @@ export class AgentSession {
|
||||
// Agent identity (registry id) used for IRC routing and job ownership.
|
||||
#agentId: string | undefined;
|
||||
#agentKind: "main" | "sub" = "main";
|
||||
#scoutAvailable = true;
|
||||
#scoutAllowedBySpawnPolicy = true;
|
||||
#providerSessionId: string | undefined;
|
||||
#freshProviderSessionId: string | undefined;
|
||||
#inheritedProviderPromptCacheKey: string | undefined;
|
||||
@@ -1238,7 +1238,7 @@ export class AgentSession {
|
||||
this.#loopGuards = new LoopGuards(streamGuardsHost);
|
||||
this.#agentId = config.agentId;
|
||||
this.#agentKind = config.agentKind ?? "main";
|
||||
this.#scoutAvailable = config.scoutAvailable ?? true;
|
||||
this.#scoutAllowedBySpawnPolicy = config.scoutAllowedBySpawnPolicy ?? true;
|
||||
this.#providerSessionId = config.providerSessionId;
|
||||
this.#inheritedProviderPromptCacheKey =
|
||||
config.providerPromptCacheKeySource === "fork" ? this.agent.promptCacheKey : undefined;
|
||||
@@ -4637,6 +4637,11 @@ export class AgentSession {
|
||||
};
|
||||
}
|
||||
|
||||
#isScoutAvailable(): boolean {
|
||||
const disabledAgents = this.settings.get("task.disabledAgents") as string[] | undefined;
|
||||
return this.#scoutAllowedBySpawnPolicy && !disabledAgents?.includes("scout");
|
||||
}
|
||||
|
||||
async #buildPlanModeMessage(): Promise<CustomMessage | null> {
|
||||
const state = this.#planModeState;
|
||||
if (!state?.enabled) return null;
|
||||
@@ -4660,7 +4665,7 @@ export class AgentSession {
|
||||
isHashlineEditMode: this.#resolveActiveEditMode() === "hashline",
|
||||
reentry: state.reentry ?? false,
|
||||
iterative: state.workflow === "iterative",
|
||||
scoutAvailable: this.#scoutAvailable,
|
||||
scoutAvailable: this.#isScoutAvailable(),
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -4794,7 +4799,7 @@ export class AgentSession {
|
||||
customType: "workflow-notice",
|
||||
content: renderWorkflowNotice({
|
||||
taskBatch: this.settings.get("task.batch"),
|
||||
scoutAvailable: this.#scoutAvailable,
|
||||
scoutAvailable: this.#isScoutAvailable(),
|
||||
}),
|
||||
display: false,
|
||||
attribution: "user",
|
||||
|
||||
@@ -144,6 +144,21 @@ describe("AgentSession magic keyword settings", () => {
|
||||
expect(notice?.content).toContain("**JavaScript (`eval`, JavaScript backend):**");
|
||||
});
|
||||
|
||||
it("updates the workflowz notice when scout is disabled during the session", async () => {
|
||||
const created = await createMagicKeywordSession(root);
|
||||
session = created.session;
|
||||
authStorage = created.authStorage;
|
||||
created.settings.set("task.disabledAgents", ["scout"]);
|
||||
const promptSpy = vi.spyOn(session.agent, "prompt").mockResolvedValue(undefined);
|
||||
|
||||
await session.prompt("please workflowz this");
|
||||
|
||||
const promptMessages = promptSpy.mock.calls[0]![0] as unknown as Array<{ content?: string; customType?: string }>;
|
||||
const notice = promptMessages.find(message => message.customType === "workflow-notice")?.content ?? "";
|
||||
expect(notice.toLowerCase()).not.toContain("scout");
|
||||
expect(notice).toContain("Explore inline FIRST");
|
||||
});
|
||||
|
||||
it("skips workflowz notice when the task tool is inactive", async () => {
|
||||
const created = await createMagicKeywordSession(root, []);
|
||||
session = created.session;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { afterEach, describe, expect, it, vi } from "bun:test";
|
||||
import { Settings } from "../../src/config/settings";
|
||||
import initAgentPrompt from "../../src/prompts/agents/init.md" with { type: "text" };
|
||||
import * as taskDiscovery from "../../src/task/discovery";
|
||||
import { TaskTool } from "../../src/task/index";
|
||||
import { isScoutSpawnable } from "../../src/task/spawn-policy";
|
||||
@@ -130,3 +131,10 @@ describe("task tool description scout gating", () => {
|
||||
expect(description).toContain("### reviewer");
|
||||
});
|
||||
});
|
||||
|
||||
describe("bundled agent prompt scout gating", () => {
|
||||
it("does not hard-code scout in the init agent prompt", () => {
|
||||
expect(initAgentPrompt.toLowerCase()).not.toContain("scout");
|
||||
expect(initAgentPrompt).toContain("multiple research agents");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user