diff --git a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.streams-soft-chunks-paragraph-preference.test.ts b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.streams-soft-chunks-paragraph-preference.test.ts index 0c2ab5702771..f94311729b7b 100644 --- a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.streams-soft-chunks-paragraph-preference.test.ts +++ b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.streams-soft-chunks-paragraph-preference.test.ts @@ -1,3 +1,5 @@ +// Soft chunking tests cover paragraph-preferred block reply splits and fenced +// code preservation during streamed assistant output. import { describe, expect, it, vi } from "vitest"; import { createParagraphChunkedBlockReplyHarness, @@ -5,6 +7,7 @@ import { } from "./embedded-agent-subscribe.e2e-harness.js"; function blockReplyTexts(onBlockReply: ReturnType): string[] { + // Helper extracts just user-visible text from emitted block reply payloads. return onBlockReply.mock.calls.map(([payload]) => (payload as { text?: string }).text ?? ""); } diff --git a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.subscribeembeddedagentsession.test.ts b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.subscribeembeddedagentsession.test.ts index eda39f5d2189..9558b186a4c4 100644 --- a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.subscribeembeddedagentsession.test.ts +++ b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.subscribeembeddedagentsession.test.ts @@ -1,3 +1,5 @@ +// End-to-end subscription tests cover usage, lifecycle, tool logging, +// messaging/media side effects, and replay-state behavior for embedded runs. import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; @@ -22,6 +24,8 @@ import { makeZeroUsageSnapshot } from "./usage.js"; describe("subscribeEmbeddedAgentSession", () => { async function flushBlockReplyCallbacks(): Promise { + // Block replies can schedule nested microtasks; drain twice before checking + // delivery state in broad subscription tests. await Promise.resolve(); await Promise.resolve(); } @@ -54,6 +58,8 @@ describe("subscribeEmbeddedAgentSession", () => { function createSubscribedHarness( options: Omit[0], "session">, ) { + // Default trusted media tools to built-ins so tests that opt into custom + // builtin sets get matching local media trust behavior. const { session, emit } = createStubSessionHarness(); subscribeEmbeddedAgentSession({ session, @@ -135,6 +141,8 @@ describe("subscribeEmbeddedAgentSession", () => { } async function captureToolLifecycleLogSubsystems(messageChannel?: string): Promise { + // Use a temporary file-backed logger so subsystem attribution is verified + // against real serialized log lines. const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-tool-log-attribution-")); const logFile = path.join(tempDir, "openclaw.log"); try { diff --git a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.suppresses-commentary-phase-output.test.ts b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.suppresses-commentary-phase-output.test.ts index a2118bcf8edf..a0dcc981289e 100644 --- a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.suppresses-commentary-phase-output.test.ts +++ b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.suppresses-commentary-phase-output.test.ts @@ -1,8 +1,12 @@ +// Commentary suppression tests ensure commentary-phase assistant messages do +// not become replies or assistantTexts before tool use. import type { AssistantMessage } from "openclaw/plugin-sdk/llm"; import { describe, expect, it, vi } from "vitest"; import { createSubscribedSessionHarness } from "./embedded-agent-subscribe.e2e-harness.js"; type AssistantMessageWithPhase = AssistantMessage & { + // Some providers expose phase on the assistant message, while others only + // include it in textSignature metadata. phase?: "commentary" | "final_answer"; }; diff --git a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.suppresses-message-end-block-replies-message-tool.test.ts b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.suppresses-message-end-block-replies-message-tool.test.ts index 9b782eb5426c..5cd9d37905b3 100644 --- a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.suppresses-message-end-block-replies-message-tool.test.ts +++ b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.suppresses-message-end-block-replies-message-tool.test.ts @@ -1,3 +1,5 @@ +// Message-tool suppression tests cover delivery tracking, source-reply mirrors, +// and duplicate reply prevention after message tool sends. import type { AssistantMessage } from "openclaw/plugin-sdk/llm"; import { describe, expect, it, vi } from "vitest"; import { @@ -9,6 +11,8 @@ import { import { subscribeEmbeddedAgentSession } from "./embedded-agent-subscribe.js"; function createBlockReplyHarness(blockReplyBreak: "message_end" | "text_end") { + // Harness exposes both emitted block replies and subscription state so tests + // can distinguish suppression from missing delivery tracking. const { session, emit } = createStubSessionHarness(); const onBlockReply = vi.fn(); const subscription = subscribeEmbeddedAgentSession({ @@ -27,6 +31,8 @@ async function emitMessageToolLifecycle(params: { media?: string; result: unknown; }) { + // Message tool sends are modeled as normal tool start/end events because the + // subscription records pending send text at start and delivery at end. params.emit({ type: "tool_execution_start", toolName: "message", @@ -97,6 +103,8 @@ describe("subscribeEmbeddedAgentSession", () => { }); it("tracks internal-ui source replies for message-tool-only final payloads", async () => { + // internal-ui source replies are not ordinary channel sends; they are stored + // for terminal payload mirroring in message_tool_only mode. const { emit, subscription } = createBlockReplyHarness("message_end"); await emitMessageToolLifecycle({ diff --git a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.waits-multiple-compaction-retries-before-resolving.test.ts b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.waits-multiple-compaction-retries-before-resolving.test.ts index d6d366f91c4a..8de7ed182bde 100644 --- a/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.waits-multiple-compaction-retries-before-resolving.test.ts +++ b/src/agents/embedded-agent-subscribe.subscribe-embedded-agent-session.waits-multiple-compaction-retries-before-resolving.test.ts @@ -1,3 +1,5 @@ +// Compaction retry subscription tests cover retry wait accounting, compaction +// event emission, abort-on-unsubscribe, and verbose tool summary behavior. import { describe, expect, it, vi } from "vitest"; import { onAgentEvent } from "../infra/agent-events.js"; import { createSubscribedSessionHarness } from "./embedded-agent-subscribe.e2e-harness.js"; @@ -8,6 +10,7 @@ function toolResultPayloadAt( ): { text?: string; } { + // Tool summary assertions only need text payloads from onToolResult calls. const [payload] = onToolResult.mock.calls[index] ?? []; if (!payload || typeof payload !== "object") { throw new Error(`expected tool result payload for call ${index + 1}`); @@ -17,6 +20,8 @@ function toolResultPayloadAt( describe("subscribeEmbeddedAgentSession", () => { it("waits for multiple compaction retries before resolving", async () => { + // Each retrying compaction requires a matching agent_end before waiters are + // released, preventing early continuation during repeated overflow repairs. const { emit, subscription } = createSubscribedSessionHarness({ runId: "run-3", });