diff --git a/scripts/deadcode-exports.baseline.mjs b/scripts/deadcode-exports.baseline.mjs index a99d9aa1854a..2b611f45e216 100644 --- a/scripts/deadcode-exports.baseline.mjs +++ b/scripts/deadcode-exports.baseline.mjs @@ -1252,9 +1252,7 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [ "src/agents/subagent-announce-dispatch.ts: mapSteerOutcomeToDeliveryResult", "src/agents/subagent-announce-output.ts: testing", "src/agents/subagent-attachments.ts: decodeStrictBase64", - "src/agents/subagent-attachments.ts: SubagentInlineAttachment", "src/agents/subagent-control.ts: testing", - "src/agents/subagent-delivery-state.ts: LegacySubagentRunRecord", "src/agents/subagent-registry-helpers.ts: resolveSubagentSessionStatus", "src/agents/subagent-registry-maintenance.ts: listSessionMaintenanceProtectedSubagentSessionKeys", "src/agents/subagent-registry-read.ts: getSubagentRunByChildSessionKey", @@ -1273,22 +1271,7 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [ "src/agents/subagent-registry.ts: resolveSubagentSessionStatus", "src/agents/subagent-registry.ts: shouldIgnorePostCompletionAnnounceForSession", "src/agents/subagent-registry.ts: testing", - "src/agents/subagent-spawn-accepted-note.ts: SUBAGENT_SPAWN_ACCEPTED_NOTE", - "src/agents/subagent-spawn-accepted-note.ts: SUBAGENT_SPAWN_SESSION_ACCEPTED_NOTE", - "src/agents/subagent-spawn.runtime.ts: forkSessionFromParent", - "src/agents/subagent-spawn.runtime.ts: ParentForkDecision", - "src/agents/subagent-spawn.runtime.ts: resolveDisplaySessionKey", - "src/agents/subagent-spawn.runtime.ts: resolveParentForkDecision", - "src/agents/subagent-spawn.ts: SpawnSubagentContextMode", - "src/agents/subagent-spawn.ts: SpawnSubagentMode", - "src/agents/subagent-spawn.ts: SpawnSubagentResult", - "src/agents/subagent-spawn.ts: SpawnSubagentSandboxMode", - "src/agents/subagent-spawn.ts: splitModelRef", - "src/agents/subagent-spawn.ts: SUBAGENT_SPAWN_ACCEPTED_NOTE", - "src/agents/subagent-spawn.ts: SUBAGENT_SPAWN_SANDBOX_MODES", - "src/agents/subagent-spawn.ts: SUBAGENT_SPAWN_SESSION_ACCEPTED_NOTE", "src/agents/subagent-spawn.ts: testing", - "src/agents/subagent-spawn.types.ts: SUBAGENT_SPAWN_SANDBOX_MODES", "src/agents/system-prompt-config.ts: resolveAgentSystemPromptConfig", "src/agents/system-prompt.ts: buildAgentBootstrapSystemContext", "src/agents/system-prompt.ts: buildAgentBootstrapSystemPromptSections", @@ -1418,7 +1401,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [ "src/auto-reply/reply/reply-usage-state.ts: clearReplyUsageStateForTest", "src/auto-reply/reply/session-fork.ts: ForkSessionEntryFromParentParams", "src/auto-reply/reply/session-fork.ts: ForkSessionEntryFromParentResult", - "src/auto-reply/reply/session-fork.ts: ParentForkDecision", "src/auto-reply/reply/session-reset-prompt.ts: buildBareSessionResetPrompt", "src/auto-reply/reply/stage-sandbox-media.ts: appendScpStderrTail", "src/auto-reply/reply/stage-sandbox-media.ts: SCP_STDERR_TAIL_CHARS", diff --git a/src/agents/openclaw-tools.subagents.sessions-spawn.cron-note.test.ts b/src/agents/openclaw-tools.subagents.sessions-spawn.cron-note.test.ts index 82b85137685a..ae60ea3e1f1b 100644 --- a/src/agents/openclaw-tools.subagents.sessions-spawn.cron-note.test.ts +++ b/src/agents/openclaw-tools.subagents.sessions-spawn.cron-note.test.ts @@ -1,10 +1,6 @@ // Verifies cron-isolated sessions suppress run-mode subagent acceptance notes. import { describe, expect, it } from "vitest"; -import { - resolveSubagentSpawnAcceptedNote, - SUBAGENT_SPAWN_ACCEPTED_NOTE, - SUBAGENT_SPAWN_SESSION_ACCEPTED_NOTE, -} from "./subagent-spawn-accepted-note.js"; +import { resolveSubagentSpawnAcceptedNote } from "./subagent-spawn-accepted-note.js"; describe("sessions_spawn: cron isolated session note suppression", () => { it("suppresses ACCEPTED_NOTE for cron isolated sessions (mode=run)", () => { @@ -17,43 +13,41 @@ describe("sessions_spawn: cron isolated session note suppression", () => { }); it("preserves ACCEPTED_NOTE for regular sessions (mode=run)", () => { - expect( - resolveSubagentSpawnAcceptedNote({ - spawnMode: "run", - agentSessionKey: "agent:main:telegram:63448508", - }), - ).toBe(SUBAGENT_SPAWN_ACCEPTED_NOTE); + const note = resolveSubagentSpawnAcceptedNote({ + spawnMode: "run", + agentSessionKey: "agent:main:telegram:63448508", + }); + + expect(note).toContain("Auto-announce is push-based"); }); it("keeps regular run guidance push-based without recommending sessions_yield", () => { // Run-mode children announce completion asynchronously, not through polling. - expect(SUBAGENT_SPAWN_ACCEPTED_NOTE).toContain("Auto-announce is push-based"); - expect(SUBAGENT_SPAWN_ACCEPTED_NOTE).toContain("Continue any independent work"); - expect(SUBAGENT_SPAWN_ACCEPTED_NOTE).toContain( - "wait for runtime completion events to arrive as user messages", - ); - expect(SUBAGENT_SPAWN_ACCEPTED_NOTE).toContain( - "only answer after completion events for ALL required children arrive", - ); - expect(SUBAGENT_SPAWN_ACCEPTED_NOTE).not.toContain("sessions_yield"); + const note = resolveSubagentSpawnAcceptedNote({ spawnMode: "run" }); + + expect(note).toContain("Auto-announce is push-based"); + expect(note).toContain("Continue any independent work"); + expect(note).toContain("wait for runtime completion events to arrive as user messages"); + expect(note).toContain("only answer after completion events for ALL required children arrive"); + expect(note).not.toContain("sessions_yield"); }); it("preserves ACCEPTED_NOTE for non-canonical cron-like keys", () => { - expect( - resolveSubagentSpawnAcceptedNote({ - spawnMode: "run", - agentSessionKey: "agent:main:slack:cron:job:run:uuid", - }), - ).toBe(SUBAGENT_SPAWN_ACCEPTED_NOTE); + const note = resolveSubagentSpawnAcceptedNote({ + spawnMode: "run", + agentSessionKey: "agent:main:slack:cron:job:run:uuid", + }); + + expect(note).toContain("Auto-announce is push-based"); }); it("preserves ACCEPTED_NOTE when agentSessionKey is undefined", () => { - expect( - resolveSubagentSpawnAcceptedNote({ - spawnMode: "run", - agentSessionKey: undefined, - }), - ).toBe(SUBAGENT_SPAWN_ACCEPTED_NOTE); + const note = resolveSubagentSpawnAcceptedNote({ + spawnMode: "run", + agentSessionKey: undefined, + }); + + expect(note).toContain("Auto-announce is push-based"); }); it("uses the session note for cron session-mode spawns", () => { @@ -62,6 +56,6 @@ describe("sessions_spawn: cron isolated session note suppression", () => { spawnMode: "session", agentSessionKey: "agent:main:cron:dd871818:run:cf959c9f", }), - ).toBe(SUBAGENT_SPAWN_SESSION_ACCEPTED_NOTE); + ).toBe("thread-bound session stays active after this task; continue in-thread for follow-ups."); }); }); diff --git a/src/agents/subagent-attachments.ts b/src/agents/subagent-attachments.ts index c39194209ad7..198e18c25ded 100644 --- a/src/agents/subagent-attachments.ts +++ b/src/agents/subagent-attachments.ts @@ -33,7 +33,7 @@ export function decodeStrictBase64(value: string, maxDecodedBytes: number): Buff return decoded; } -export type SubagentInlineAttachment = { +type SubagentInlineAttachment = { name: string; content: string; encoding?: "utf8" | "base64"; diff --git a/src/agents/subagent-delivery-state.test.ts b/src/agents/subagent-delivery-state.test.ts index c716bf8112fb..f1584a2ef865 100644 --- a/src/agents/subagent-delivery-state.test.ts +++ b/src/agents/subagent-delivery-state.test.ts @@ -2,9 +2,10 @@ // nested completion/delivery shape used by current registry records. import { describe, expect, it } from "vitest"; import { normalizeSubagentRunState } from "./subagent-delivery-state.js"; -import type { LegacySubagentRunRecord } from "./subagent-delivery-state.js"; import type { SubagentRunRecord } from "./subagent-registry.types.js"; +type LegacySubagentRunRecord = SubagentRunRecord & Record; + function baseRun(overrides: Partial = {}): LegacySubagentRunRecord { return { runId: "run-1", diff --git a/src/agents/subagent-delivery-state.ts b/src/agents/subagent-delivery-state.ts index f32be6ab91f3..b967ada8bc9c 100644 --- a/src/agents/subagent-delivery-state.ts +++ b/src/agents/subagent-delivery-state.ts @@ -12,7 +12,7 @@ import type { } from "./subagent-registry.types.js"; /** Legacy flat fields accepted while restoring older subagent registry rows. */ -export type LegacySubagentRunRecord = SubagentRunRecord & { +type LegacySubagentRunRecord = SubagentRunRecord & { announceRetryCount?: number; lastAnnounceRetryAt?: number; lastAnnounceDeliveryError?: string; diff --git a/src/agents/subagent-spawn-accepted-note.ts b/src/agents/subagent-spawn-accepted-note.ts index 55fcdd61d831..fd0f42a7bda7 100644 --- a/src/agents/subagent-spawn-accepted-note.ts +++ b/src/agents/subagent-spawn-accepted-note.ts @@ -5,9 +5,9 @@ */ import { isCronSessionKey } from "../routing/session-key.js"; -export const SUBAGENT_SPAWN_ACCEPTED_NOTE = +const SUBAGENT_SPAWN_ACCEPTED_NOTE = "Auto-announce is push-based. After spawning children, do NOT call sessions_list, sessions_history, exec sleep, or any polling tool. Track expected child session keys. Continue any independent work. If your final answer depends on child output, wait for runtime completion events to arrive as user messages and only answer after completion events for ALL required children arrive. If a child completion event arrives AFTER your final answer, reply ONLY with NO_REPLY."; -export const SUBAGENT_SPAWN_SESSION_ACCEPTED_NOTE = +const SUBAGENT_SPAWN_SESSION_ACCEPTED_NOTE = "thread-bound session stays active after this task; continue in-thread for follow-ups."; /** Resolve the post-spawn note, suppressing polling guidance for cron sessions. */ diff --git a/src/agents/subagent-spawn.runtime.ts b/src/agents/subagent-spawn.runtime.ts index c28b7e1eabe6..ccbc338091c1 100644 --- a/src/agents/subagent-spawn.runtime.ts +++ b/src/agents/subagent-spawn.runtime.ts @@ -9,12 +9,7 @@ export { } from "../config/agent-limits.js"; export { getRuntimeConfig } from "../config/config.js"; export { loadSessionEntry, upsertSessionEntry } from "../config/sessions/session-accessor.js"; -export { - forkSessionEntryFromParent, - forkSessionFromParent, - resolveParentForkDecision, - type ParentForkDecision, -} from "../auto-reply/reply/session-fork.js"; +export { forkSessionEntryFromParent } from "../auto-reply/reply/session-fork.js"; export { ensureContextEnginesInitialized } from "../context-engine/init.js"; export { resolveContextEngine } from "../context-engine/registry.js"; export { callGateway } from "../gateway/call.js"; @@ -38,8 +33,4 @@ export { resolveAgentConfig } from "./agent-scope.js"; export { AGENT_LANE_SUBAGENT } from "./lanes.js"; export { resolveSandboxRuntimeStatus } from "./sandbox/runtime-status.js"; export { buildSubagentSystemPrompt } from "./subagent-system-prompt.js"; -export { - resolveDisplaySessionKey, - resolveInternalSessionKey, - resolveMainSessionAlias, -} from "./tools/sessions-helpers.js"; +export { resolveInternalSessionKey, resolveMainSessionAlias } from "./tools/sessions-helpers.js"; diff --git a/src/agents/subagent-spawn.ts b/src/agents/subagent-spawn.ts index a86efc054c3a..2e223fc5071a 100644 --- a/src/agents/subagent-spawn.ts +++ b/src/agents/subagent-spawn.ts @@ -51,6 +51,7 @@ import { resolvePersistedSelectedModelRef, } from "./model-selection.js"; import { resolveThinkingDefault } from "./model-thinking-default.js"; +import { resolveRequesterOriginForChild } from "./spawn-requester-origin.js"; import { mapToolContextToSpawnedRunMetadata, normalizeSpawnedRunMetadata, @@ -67,13 +68,6 @@ import { countActiveRunsForSession, registerSubagentRun } from "./subagent-regis import { resolveSubagentRunTimerDelayMs } from "./subagent-run-timeout.js"; import { resolveSubagentSpawnAcceptedNote } from "./subagent-spawn-accepted-note.js"; import { resolveSubagentSpawnOwnership } from "./subagent-spawn-ownership.js"; -import { resolveSubagentTargetPolicy } from "./subagent-target-policy.js"; -import { normalizeSubagentTaskName } from "./subagent-task-name.js"; -export { - SUBAGENT_SPAWN_ACCEPTED_NOTE, - SUBAGENT_SPAWN_SESSION_ACCEPTED_NOTE, -} from "./subagent-spawn-accepted-note.js"; -import { resolveRequesterOriginForChild } from "./spawn-requester-origin.js"; import { resolveConfiguredSubagentRunTimeoutSeconds, resolveSubagentModelAndThinkingPlan, @@ -111,17 +105,10 @@ import type { SpawnSubagentMode, SpawnSubagentSandboxMode, } from "./subagent-spawn.types.js"; +import { resolveSubagentTargetPolicy } from "./subagent-target-policy.js"; +import { normalizeSubagentTaskName } from "./subagent-task-name.js"; -export { - SUBAGENT_SPAWN_CONTEXT_MODES, - SUBAGENT_SPAWN_MODES, - SUBAGENT_SPAWN_SANDBOX_MODES, -} from "./subagent-spawn.types.js"; -export type { - SpawnSubagentContextMode, - SpawnSubagentMode, - SpawnSubagentSandboxMode, -} from "./subagent-spawn.types.js"; +export { SUBAGENT_SPAWN_CONTEXT_MODES, SUBAGENT_SPAWN_MODES } from "./subagent-spawn.types.js"; function resolveConfiguredAgentIds(cfg: OpenClawConfig): string[] { return listAgentIds(cfg); @@ -198,7 +185,7 @@ type SpawnSubagentContext = { inheritedToolDenylist?: string[]; }; -export type SpawnSubagentResult = { +type SpawnSubagentResult = { status: "accepted" | "forbidden" | "error"; childSessionKey?: string; runId?: string; @@ -219,8 +206,6 @@ export type SpawnSubagentResult = { }; }; -export { splitModelRef } from "./subagent-spawn-plan.js"; - async function callSubagentGateway( params: Parameters[0], ): Promise>> { diff --git a/src/agents/subagent-spawn.types.ts b/src/agents/subagent-spawn.types.ts index d9a85391ca3f..96816e7c58fe 100644 --- a/src/agents/subagent-spawn.types.ts +++ b/src/agents/subagent-spawn.types.ts @@ -5,7 +5,7 @@ export const SUBAGENT_SPAWN_MODES = ["run", "session"] as const; export type SpawnSubagentMode = (typeof SUBAGENT_SPAWN_MODES)[number]; /** Sandbox escalation policy requested for a spawned subagent. */ -export const SUBAGENT_SPAWN_SANDBOX_MODES = ["inherit", "require"] as const; +const SUBAGENT_SPAWN_SANDBOX_MODES = ["inherit", "require"] as const; export type SpawnSubagentSandboxMode = (typeof SUBAGENT_SPAWN_SANDBOX_MODES)[number]; /** Prompt context relationship between the parent session and spawned subagent. */ diff --git a/src/auto-reply/reply/session-fork.ts b/src/auto-reply/reply/session-fork.ts index 9437b339960d..af78a3c36900 100644 --- a/src/auto-reply/reply/session-fork.ts +++ b/src/auto-reply/reply/session-fork.ts @@ -24,7 +24,7 @@ function assertParentSessionForkAllowed(parentEntry: SessionEntry): void { } } -export type ParentForkDecision = SessionParentForkDecision; +type ParentForkDecision = SessionParentForkDecision; type ParentForkDecisionParams = { parentEntry: SessionEntry;