docs: document subagent control tests · openclaw/openclaw@a9224f6
steipete
·
2026-06-05
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Subagent announce format e2e tests exercise the full announce flow with |
| 2 | +// channel fixtures, session stores, hooks, and gateway calls wired together. |
1 | 3 | import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; |
2 | 4 | import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js"; |
3 | 5 | import { |
@@ -80,6 +82,8 @@ function expectInputProvenance(
|
80 | 82 | params: Record<string, unknown> | undefined, |
81 | 83 | sourceSessionKey: string, |
82 | 84 | ) { |
| 85 | +// Announce handoffs are inter-session messages; provenance lets the receiver |
| 86 | +// distinguish child-output delivery from ordinary user input. |
83 | 87 | const inputProvenance = params?.inputProvenance; |
84 | 88 | if (!inputProvenance || typeof inputProvenance !== "object") { |
85 | 89 | throw new Error("Expected input provenance"); |
@@ -218,6 +222,8 @@ const defaultOutcomeAnnounce = {
|
218 | 222 | }; |
219 | 223 | |
220 | 224 | const announceFormatChannelPlugins = [ |
| 225 | +// Channel fixtures intentionally mix plain channels with Slack-style thread |
| 226 | +// target resolution so formatting covers direct and threaded destinations. |
221 | 227 | { |
222 | 228 | pluginId: "discord", |
223 | 229 | plugin: createChannelTestPluginBase({ id: "discord", label: "Discord" }), |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Subagent announce flow tests cover the seam-level orchestration between wait |
| 2 | +// outcomes, requester lookup, delivery, and cleanup. |
1 | 3 | import { beforeEach, describe, expect, it, vi } from "vitest"; |
2 | 4 | import type { EmbeddedAgentQueueMessageOutcome } from "./embedded-agent-runner/runs.js"; |
3 | 5 | import { createSubagentAnnounceDeliveryRuntimeMock } from "./subagent-announce.test-support.js"; |
@@ -108,6 +110,8 @@ vi.mock("./subagent-announce-delivery.js", () => ({
|
108 | 110 | requesterSessionOrigin?: { provider?: string; channel?: string }; |
109 | 111 | bestEffortDeliver?: boolean; |
110 | 112 | }) => { |
| 113 | +// The delivery mock preserves the key branch: active Discord requester |
| 114 | +// sessions are steered in-process, while inactive/direct paths call agent. |
111 | 115 | const store = loadSessionStoreMock("/tmp/sessions.json") as Record<string, unknown>; |
112 | 116 | const requesterEntry = (store?.[params.targetRequesterSessionKey] ?? {}) as |
113 | 117 | | { sessionId?: string; origin?: { provider?: string; channel?: string } } |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Subagent announce timeout tests cover retry timing and fallback requester |
| 2 | +// resolution when completion delivery cannot finish immediately. |
1 | 3 | import { clampTimerTimeoutMs } from "@openclaw/normalization-core/number-coercion"; |
2 | 4 | import { beforeEach, describe, expect, it, vi } from "vitest"; |
3 | 5 | import { createSubagentAnnounceDeliveryRuntimeMock } from "./subagent-announce.test-support.js"; |
@@ -110,6 +112,8 @@ vi.mock("./subagent-announce-delivery.js", () => ({
|
110 | 112 | directIdempotencyKey?: string; |
111 | 113 | internalEvents?: unknown; |
112 | 114 | }) => { |
| 115 | +// Retry behavior is modeled here because the outer announce flow only sees |
| 116 | +// whether direct delivery eventually succeeded or failed. |
113 | 117 | const buildRequest = () => ({ |
114 | 118 | method: "agent", |
115 | 119 | expectFinal: true, |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Subagent control tests cover sending, steering, killing, and admin cleanup of |
| 2 | +// child runs recorded in the subagent registry and session store. |
1 | 3 | import fs from "node:fs"; |
2 | 4 | import os from "node:os"; |
3 | 5 | import path from "node:path"; |
@@ -30,6 +32,8 @@ vi.mock("./run-wait.js", () => {
|
30 | 32 | limit?: number; |
31 | 33 | callGateway?: (request: CallGatewayOptions) => Promise<{ messages?: unknown[] }>; |
32 | 34 | }) => { |
| 35 | +// The real helper snapshots assistant fingerprints so a steer command only |
| 36 | +// reports new replies, not the baseline text that existed before steering. |
33 | 37 | const history = await params.callGateway?.({ |
34 | 38 | method: "chat.history", |
35 | 39 | params: { sessionKey: params.sessionKey, limit: params.limit ?? 50 }, |
@@ -111,6 +115,8 @@ vi.mock("./run-wait.js", () => {
|
111 | 115 | function setSubagentControlDepsForTest( |
112 | 116 | overrides: Parameters<typeof testing.setDepsForTest>[0] = {}, |
113 | 117 | ) { |
| 118 | +// Tests use real JSON store mutation to catch persisted cleanup/kill state, |
| 119 | +// while swapping process-owned queues and embedded-run aborts for fakes. |
114 | 120 | testing.setDepsForTest({ |
115 | 121 | abortEmbeddedAgentRun: () => false, |
116 | 122 | clearSessionQueues: () => ({ followupCleared: 0, laneCleared: 0, keys: [] }), |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Subagent delivery-state tests cover migration of legacy run fields into the |
| 2 | +// nested completion/delivery shape used by current registry records. |
1 | 3 | import { describe, expect, it } from "vitest"; |
2 | 4 | import { normalizeSubagentRunState } from "./subagent-delivery-state.js"; |
3 | 5 | import type { LegacySubagentRunRecord } from "./subagent-delivery-state.js"; |
@@ -22,6 +24,8 @@ function baseRun(overrides: Partial<LegacySubagentRunRecord> = {}): LegacySubage
|
22 | 24 | |
23 | 25 | describe("normalizeSubagentRunState", () => { |
24 | 26 | it("migrates legacy pending delivery fields into nested completion and delivery state", () => { |
| 27 | +// Restored runs may still carry flat pendingFinalDelivery fields from older |
| 28 | +// builds; normalization must preserve retry payloads before stripping them. |
25 | 29 | const entry = normalizeSubagentRunState( |
26 | 30 | baseRun({ |
27 | 31 | frozenResultText: "child output", |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +// Subagent depth tests cover depth recovery from persisted session metadata and |
| 2 | +// timer-safe timeout normalization for spawned agent runs. |
1 | 3 | import fs from "node:fs"; |
2 | 4 | import os from "node:os"; |
3 | 5 | import path from "node:path"; |
@@ -40,6 +42,8 @@ describe("getSubagentDepthFromSessionStore", () => {
|
40 | 42 | }); |
41 | 43 | |
42 | 44 | it("derives depth from spawnedBy ancestry when spawnDepth is missing", () => { |
| 45 | +// Ancestry fallback keeps restored sessions useful when old stores predate |
| 46 | +// the explicit spawnDepth field. |
43 | 47 | const key1 = "agent:main:subagent:one"; |
44 | 48 | const key2 = "agent:main:subagent:two"; |
45 | 49 | const key3 = "agent:main:subagent:three"; |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。