mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
refactor(agents): move announce, completion, recovery, and registry families into concept directories (#121553)
* refactor(agents): move announce family into subagents/announce/ * refactor(agents): move completion and main-session recovery families * refactor(agents): move registry family into subagents/registry * refactor(agents): update registry state type imports * style(agents): format moved subagent imports * test(agents): preserve isolated registry test routing * fix(scripts): recognize relocated subagent announce seams
This commit is contained in:
committed by
GitHub
parent
2132c15bd6
commit
1ced7441eb
@@ -156,9 +156,9 @@ const rootEntries = [
|
||||
// Loaded by URL from setup-inference-detection.ts; no static import edge exists.
|
||||
"src/system-agent/setup-inference-detection.worker.ts!",
|
||||
// Split runtime loaded through a path assembled in subagent-registry.ts.
|
||||
"src/agents/subagent-registry.runtime.ts!",
|
||||
"src/agents/subagents/registry/subagent-registry.runtime.ts!",
|
||||
// Loaded lazily by the sweeper only when a receipt-bearing or interrupted row is found.
|
||||
"src/agents/subagent-registry-restart-recovery.ts!",
|
||||
"src/agents/subagents/registry/subagent-registry-restart-recovery.ts!",
|
||||
// Task cancellation loads this control facade by string path to avoid a registry cycle.
|
||||
"src/tasks/task-registry-control.runtime.ts!",
|
||||
// Human plugin listing lazily loads its formatter to keep JSON startup lean.
|
||||
|
||||
@@ -409,7 +409,7 @@ src/agents/failover-error.ts
|
||||
src/agents/harness/native-hook-relay.test.ts
|
||||
src/agents/harness/selection.test.ts
|
||||
src/agents/harness/selection.ts
|
||||
src/agents/main-session-restart-recovery.test.ts
|
||||
src/agents/main-session-recovery/main-session-restart-recovery.test.ts
|
||||
src/agents/model-auth-availability.ts
|
||||
src/agents/model-auth.profiles.test.ts
|
||||
src/agents/model-auth.test.ts
|
||||
@@ -441,15 +441,15 @@ src/agents/sessions/model-registry.ts
|
||||
src/agents/sessions/package-manager.ts
|
||||
src/agents/sessions/resource-loader.ts
|
||||
src/agents/sessions/settings-manager.ts
|
||||
src/agents/subagent-announce-delivery.test.ts
|
||||
src/agents/subagent-announce-delivery.ts
|
||||
src/agents/subagent-announce.format.e2e.test.ts
|
||||
src/agents/subagent-control.test.ts
|
||||
src/agents/subagent-control.ts
|
||||
src/agents/subagent-registry-lifecycle.test.ts
|
||||
src/agents/subagent-registry-run-manager.ts
|
||||
src/agents/subagent-registry.steer-restart.test.ts
|
||||
src/agents/subagent-registry.test.ts
|
||||
src/agents/subagents/announce/subagent-announce-delivery.test.ts
|
||||
src/agents/subagents/announce/subagent-announce-delivery.ts
|
||||
src/agents/subagents/announce/subagent-announce.format.e2e.test.ts
|
||||
src/agents/subagents/registry/subagent-control.test.ts
|
||||
src/agents/subagents/registry/subagent-control.ts
|
||||
src/agents/subagents/registry/subagent-registry-lifecycle.test.ts
|
||||
src/agents/subagents/registry/subagent-registry-run-manager.ts
|
||||
src/agents/subagents/registry/subagent-registry.steer-restart.test.ts
|
||||
src/agents/subagents/registry/subagent-registry.test.ts
|
||||
src/agents/subagents/spawn/subagent-spawn.test.ts
|
||||
src/agents/system-prompt.test.ts
|
||||
src/agents/system-prompt.ts
|
||||
|
||||
@@ -50,7 +50,7 @@ This table records the implementation state when #103505 was opened. The rollout
|
||||
| Portable actions | `src/interactive/payload.ts`, `src/plugin-sdk/interactive-runtime.ts`, `src/plugin-sdk/approval-reply-runtime.ts` | Approval buttons are command actions containing `/approve ...`; URL and Web App targets are untyped button fields. |
|
||||
| Telegram | `extensions/telegram/src/approval-handler.runtime.ts`, `extensions/telegram/src/button-types.ts` | The renderer parses command text to recognize approval semantics before producing private callback data. |
|
||||
| Control UI | `ui/src/app/exec-approval.ts`, `ui/src/app/overlays.ts`, `ui/src/components/exec-approval.ts` | Approval UI is a global modal. `ui/src/app-route-paths.ts` and `ui/src/app-routes.ts` use exact routes and rewrite unknown paths to Chat. |
|
||||
| Session ownership | `src/agents/subagent-registry.types.ts`, `src/agents/subagent-registry-read.ts`, `src/config/sessions/types.ts` | Controller, requester, explicit parent, and legacy spawn ownership exist, but approval events are not projected to those session streams. |
|
||||
| Session ownership | `src/agents/subagents/registry/subagent-registry.types.ts`, `src/agents/subagents/registry/subagent-registry-read.ts`, `src/config/sessions/types.ts` | Controller, requester, explicit parent, and legacy spawn ownership exist, but approval events are not projected to those session streams. |
|
||||
| Shared state | `src/state/openclaw-state-schema.sql`, `src/state/openclaw-state-db.ts` | Existing immediate transactions and Kysely conditional updates support durable compare-and-set in `state/openclaw.sqlite`. |
|
||||
|
||||
Representative current tests include `src/gateway/exec-approval-manager.test.ts`, `src/gateway/server-methods/approval-shared.test.ts`, `src/agents/bash-tools.exec-gateway-approval.e2e.test.ts`, `extensions/telegram/src/approval-handler.runtime.test.ts`, and `ui/src/e2e/approval-flow.e2e.test.ts`.
|
||||
@@ -294,7 +294,7 @@ Use a deterministic breadth-first walk:
|
||||
4. Normalize and de-duplicate on enqueue so the first, shortest path wins.
|
||||
5. Stop at 64 unique keys; this audience-size cap also bounds traversal depth.
|
||||
|
||||
The registry source is `src/agents/subagent-registry-read.ts`; ownership fields are defined in `src/agents/subagent-registry.types.ts`. Session fallback fields are defined in `src/config/sessions/types.ts`.
|
||||
The registry source is `src/agents/subagents/registry/subagent-registry-read.ts`; ownership fields are defined in `src/agents/subagents/registry/subagent-registry.types.ts`. Session fallback fields are defined in `src/config/sessions/types.ts`.
|
||||
|
||||
Requested and terminal projections use the same persisted audience even if focus/controller ownership changes while the approval is pending. This guarantees terminal cleanup for every audience session stream that received the request projection. Resolution always targets the source approval ID; audience sessions never receive cloned approval state. Forwarded channel-message cleanup remains the separate delivery-locator follow-up below.
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ scenario:
|
||||
- docs/help/testing.md
|
||||
codeRefs:
|
||||
- src/agents/requester-tool-policy.ts
|
||||
- src/agents/subagent-announce-delivery.ts
|
||||
- src/agents/subagent-capabilities.ts
|
||||
- src/agents/subagents/announce/subagent-announce-delivery.ts
|
||||
- src/agents/subagents/spawn/subagent-capabilities.ts
|
||||
- src/agents/tools/sessions-yield-tool.ts
|
||||
execution:
|
||||
kind: flow
|
||||
|
||||
@@ -30,7 +30,7 @@ scenario:
|
||||
- src/agents/conversation-capability-profile.ts
|
||||
- src/agents/requester-tool-policy.ts
|
||||
- src/agents/sender-tool-policy.ts
|
||||
- src/agents/subagent-capabilities.ts
|
||||
- src/agents/subagents/spawn/subagent-capabilities.ts
|
||||
execution:
|
||||
kind: flow
|
||||
suiteIsolation: isolated
|
||||
|
||||
@@ -32,8 +32,8 @@ scenario:
|
||||
- docs/channels/qa-channel.md
|
||||
codeRefs:
|
||||
- src/agents/agent-run-terminal-reply.ts
|
||||
- src/agents/subagent-announce-delivery.ts
|
||||
- src/agents/subagent-registry-lifecycle.ts
|
||||
- src/agents/subagents/announce/subagent-announce-delivery.ts
|
||||
- src/agents/subagents/registry/subagent-registry-lifecycle.ts
|
||||
- extensions/qa-lab/src/providers/mock-openai/server.ts
|
||||
execution:
|
||||
kind: flow
|
||||
|
||||
@@ -20,7 +20,7 @@ scenario:
|
||||
- docs/help/testing.md
|
||||
codeRefs:
|
||||
- src/gateway/session-utils.ts
|
||||
- src/agents/subagent-run-liveness.ts
|
||||
- src/agents/subagents/registry/subagent-run-liveness.ts
|
||||
- extensions/qa-lab/src/gateway-child.ts
|
||||
execution:
|
||||
kind: flow
|
||||
|
||||
@@ -31,7 +31,7 @@ scenario:
|
||||
codeRefs:
|
||||
- extensions/qa-lab/src/suite-runtime-agent-session.ts
|
||||
- extensions/qa-lab/src/suite-runtime-gateway.ts
|
||||
- src/agents/main-session-restart-recovery.ts
|
||||
- src/agents/main-session-recovery/main-session-restart-recovery.ts
|
||||
execution:
|
||||
kind: flow
|
||||
summary: Run a fixture-backed audit with GPT-5.4 while replacing the Gateway child three times at durable wait checkpoints.
|
||||
|
||||
@@ -686,8 +686,8 @@ function describeSubagentSeamKinds(relativePath: string, source: string) {
|
||||
|
||||
const seamKinds = [];
|
||||
const isAnnounceDispatchPath =
|
||||
relativePath === "src/agents/subagent-announce.ts" ||
|
||||
relativePath === "src/agents/subagent-announce-dispatch.ts";
|
||||
relativePath === "src/agents/subagents/announce/subagent-announce.ts" ||
|
||||
relativePath === "src/agents/subagents/announce/subagent-announce-dispatch.ts";
|
||||
const importsSpawnRuntime = hasAnyImportSource(source, [
|
||||
"./subagent-spawn.js",
|
||||
"./acp-spawn.js",
|
||||
@@ -718,6 +718,8 @@ function describeSubagentSeamKinds(relativePath: string, source: string) {
|
||||
const importsAnnounceDelivery = hasAnyImportSource(source, [
|
||||
"./subagent-announce.js",
|
||||
"./subagent-announce-dispatch.js",
|
||||
"../announce/subagent-announce.js",
|
||||
"../announce/subagent-announce-dispatch.js",
|
||||
"./subagent-announce-queue.js",
|
||||
"../infra/outbound/bound-delivery-router.js",
|
||||
"../utils/delivery-context.shared.js",
|
||||
|
||||
@@ -3,7 +3,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { performance } from "node:perf_hooks";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import type { SubagentRunRecord } from "../src/agents/subagent-registry.types.js";
|
||||
import type { SubagentRunRecord } from "../src/agents/subagents/registry/subagent-registry.types.js";
|
||||
import type { DB as OpenClawStateKyselyDatabase } from "../src/state/openclaw-state-db.generated.js";
|
||||
import {
|
||||
WORKER_RESULT_SENTINEL,
|
||||
@@ -102,7 +102,7 @@ async function drainSpawnSampleRootWork(
|
||||
|
||||
async function resetRuntime(persist: boolean): Promise<void> {
|
||||
const [subagents, tasks, stateDb, agentDb] = await Promise.all([
|
||||
import("../src/agents/subagent-registry.test-helpers.js"),
|
||||
import("../src/agents/subagents/registry/subagent-registry.test-helpers.js"),
|
||||
import("../src/tasks/task-runtime.test-helpers.js"),
|
||||
import("../src/state/openclaw-state-db.js"),
|
||||
import("../src/state/openclaw-agent-db.js"),
|
||||
@@ -184,8 +184,8 @@ async function configureSpawnRuntime(
|
||||
callGateway: typeof import("../src/gateway/call.js").callGateway,
|
||||
): Promise<void> {
|
||||
const [subagents, registry, taskStore, flowStore] = await Promise.all([
|
||||
import("../src/agents/subagent-registry.test-helpers.js"),
|
||||
import("../src/agents/subagent-registry-memory.js"),
|
||||
import("../src/agents/subagents/registry/subagent-registry.test-helpers.js"),
|
||||
import("../src/agents/subagents/registry/subagent-registry-memory.js"),
|
||||
import("../src/tasks/task-registry.store.js"),
|
||||
import("../src/tasks/task-flow-registry.store.test-support.js"),
|
||||
]);
|
||||
@@ -315,7 +315,7 @@ async function runSpawnSample(
|
||||
): Promise<Sample> {
|
||||
const [pipeline, registry] = await Promise.all([
|
||||
import("../src/agents/spawn-pipeline.js"),
|
||||
import("../src/agents/subagent-registry-memory.js"),
|
||||
import("../src/agents/subagents/registry/subagent-registry-memory.js"),
|
||||
]);
|
||||
await resetRuntime(mode === "durable");
|
||||
const barrier = createTerminalWaitBarrier();
|
||||
@@ -595,8 +595,8 @@ async function runSweepSample(childCount: number): Promise<Sample> {
|
||||
{ getSubagentRunsForChildSession, subagentRuns: runs },
|
||||
{ createSubagentRegistrySweeper },
|
||||
] = await Promise.all([
|
||||
import("../src/agents/subagent-registry-memory.js"),
|
||||
import("../src/agents/subagent-registry-sweeper.js"),
|
||||
import("../src/agents/subagents/registry/subagent-registry-memory.js"),
|
||||
import("../src/agents/subagents/registry/subagent-registry-sweeper.js"),
|
||||
]);
|
||||
const now = Date.now();
|
||||
runs.clear();
|
||||
@@ -694,7 +694,7 @@ async function runSweepSample(childCount: number): Promise<Sample> {
|
||||
|
||||
async function runDedupeSample(childCount: number): Promise<Sample> {
|
||||
const { dedupeLatestChildCompletionRows } =
|
||||
await import("../src/agents/subagent-announce-output.js");
|
||||
await import("../src/agents/subagents/announce/subagent-announce-output.js");
|
||||
const rowsForOrder = (generations: number[]) =>
|
||||
Array.from({ length: childCount }, (_, child) =>
|
||||
generations.map((generation) => ({
|
||||
|
||||
@@ -109,8 +109,8 @@ export const migratedSessionAccessorFiles = new Set([
|
||||
"src/agents/embedded-agent-runner/transcript-rewrite.ts",
|
||||
"src/agents/embedded-agent-runner/transcript-runtime-state.ts",
|
||||
"src/agents/live-model-switch.ts",
|
||||
"src/agents/subagent-control.ts",
|
||||
"src/agents/subagent-registry-helpers.ts",
|
||||
"src/agents/subagents/registry/subagent-control.ts",
|
||||
"src/agents/subagents/registry/subagent-registry-helpers.ts",
|
||||
"src/auto-reply/reply/abort.ts",
|
||||
"src/auto-reply/reply/agent-runner-helpers.ts",
|
||||
"src/auto-reply/reply/agent-runner.ts",
|
||||
@@ -187,13 +187,13 @@ export const migratedSessionAccessorWriteFiles = new Set([
|
||||
"src/agents/embedded-agent-subscribe.handlers.compaction.runtime.ts",
|
||||
"src/agents/embedded-agent-runner/run/attempt.ts",
|
||||
"src/agents/live-model-switch.ts",
|
||||
"src/agents/main-session-restart-recovery-checkpoint.ts",
|
||||
"src/agents/main-session-restart-recovery-marking.ts",
|
||||
"src/agents/main-session-restart-recovery-store.ts",
|
||||
"src/agents/main-session-recovery/main-session-restart-recovery-checkpoint.ts",
|
||||
"src/agents/main-session-recovery/main-session-restart-recovery-marking.ts",
|
||||
"src/agents/main-session-recovery/main-session-restart-recovery-store.ts",
|
||||
"src/agents/session-suspension.ts",
|
||||
"src/auto-reply/reply/abort.ts",
|
||||
"src/agents/subagent-control.ts",
|
||||
"src/agents/subagent-registry-helpers.ts",
|
||||
"src/agents/subagents/registry/subagent-control.ts",
|
||||
"src/agents/subagents/registry/subagent-registry-helpers.ts",
|
||||
"src/agents/tools/session-status-tool.ts",
|
||||
"src/auto-reply/reply/abort-cutoff.runtime.ts",
|
||||
"src/auto-reply/reply/agent-runner-cli-dispatch.ts",
|
||||
|
||||
@@ -69,12 +69,12 @@ const gatewaySessionServerMethodFiles = [
|
||||
];
|
||||
|
||||
export const migratedSessionTranscriptReaderFiles = new Set([
|
||||
"src/agents/main-session-restart-recovery-store.ts",
|
||||
"src/agents/subagent-announce-output.test.ts",
|
||||
"src/agents/subagent-announce-output.ts",
|
||||
"src/agents/subagent-announce.runtime.ts",
|
||||
"src/agents/subagent-registry-restart-recovery.test.ts",
|
||||
"src/agents/subagent-registry-restart-recovery.ts",
|
||||
"src/agents/main-session-recovery/main-session-restart-recovery-store.ts",
|
||||
"src/agents/subagents/announce/subagent-announce-output.test.ts",
|
||||
"src/agents/subagents/announce/subagent-announce-output.ts",
|
||||
"src/agents/subagents/announce/subagent-announce.runtime.ts",
|
||||
"src/agents/subagents/registry/subagent-registry-restart-recovery.test.ts",
|
||||
"src/agents/subagents/registry/subagent-registry-restart-recovery.ts",
|
||||
"src/agents/tools/embedded-gateway-stub.runtime.ts",
|
||||
"src/agents/tools/embedded-gateway-stub.test.ts",
|
||||
"src/agents/tools/embedded-gateway-stub.ts",
|
||||
|
||||
@@ -200,15 +200,15 @@
|
||||
{
|
||||
"name": "countActiveDescendantRuns",
|
||||
"files": [
|
||||
"src/agents/subagent-registry-read.ts",
|
||||
"src/agents/subagent-registry.ts"
|
||||
"src/agents/subagents/registry/subagent-registry-read.ts",
|
||||
"src/agents/subagents/registry/subagent-registry.ts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "countPendingDescendantRuns",
|
||||
"files": [
|
||||
"src/agents/subagent-registry-announce-read.ts",
|
||||
"src/agents/subagent-registry.ts"
|
||||
"src/agents/subagents/registry/subagent-registry-announce-read.ts",
|
||||
"src/agents/subagents/registry/subagent-registry.ts"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -524,8 +524,8 @@
|
||||
{
|
||||
"name": "getLatestSubagentRunByChildSessionKey",
|
||||
"files": [
|
||||
"src/agents/subagent-registry-read.ts",
|
||||
"src/agents/subagent-registry.ts"
|
||||
"src/agents/subagents/registry/subagent-registry-read.ts",
|
||||
"src/agents/subagents/registry/subagent-registry.ts"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -672,8 +672,8 @@
|
||||
{
|
||||
"name": "listDescendantRunsForRequester",
|
||||
"files": [
|
||||
"src/agents/subagent-registry-read.ts",
|
||||
"src/agents/subagent-registry.ts"
|
||||
"src/agents/subagents/registry/subagent-registry-read.ts",
|
||||
"src/agents/subagents/registry/subagent-registry.ts"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -702,8 +702,8 @@
|
||||
{
|
||||
"name": "listSubagentRunsForController",
|
||||
"files": [
|
||||
"src/agents/subagent-registry-read.ts",
|
||||
"src/agents/subagent-registry.ts"
|
||||
"src/agents/subagents/registry/subagent-registry-read.ts",
|
||||
"src/agents/subagents/registry/subagent-registry.ts"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -806,7 +806,7 @@
|
||||
"files": [
|
||||
"src/agents/auth-profiles/constants.ts",
|
||||
"src/agents/embedded-agent-runner/logger.ts",
|
||||
"src/agents/main-session-restart-recovery-shared.ts",
|
||||
"src/agents/main-session-recovery/main-session-restart-recovery-shared.ts",
|
||||
"src/system-agent/setup-inference-core.ts",
|
||||
"src/tasks/task-registry-state.ts"
|
||||
]
|
||||
@@ -1081,7 +1081,7 @@
|
||||
{
|
||||
"name": "readSessionEntry",
|
||||
"files": [
|
||||
"src/agents/subagent-announce.runtime.ts",
|
||||
"src/agents/subagents/announce/subagent-announce.runtime.ts",
|
||||
"src/cron/isolated-agent.turn-test-helpers.ts"
|
||||
]
|
||||
},
|
||||
@@ -1184,8 +1184,8 @@
|
||||
{
|
||||
"name": "replaceSubagentRunAfterSteer",
|
||||
"files": [
|
||||
"src/agents/subagent-registry-runtime.ts",
|
||||
"src/agents/subagent-registry.ts"
|
||||
"src/agents/subagents/registry/subagent-registry-runtime.ts",
|
||||
"src/agents/subagents/registry/subagent-registry.ts"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"embeddedAgentSessionTarget": {},
|
||||
"memoryHostSessionCorpus": {},
|
||||
"sessionAccessorRead": {
|
||||
"src/agents/subagent-announce-output.ts": 3,
|
||||
"src/agents/subagent-announce.test-support.ts": 2,
|
||||
"src/agents/subagents/announce/subagent-announce-output.ts": 3,
|
||||
"src/agents/subagents/announce/subagent-announce.test-support.ts": 2,
|
||||
"src/agents/tools/transcripts-tool.ts": 2,
|
||||
"src/auto-reply/reply/commands-session-store.ts": 2,
|
||||
"src/config/sessions/session-accessor.entry.ts": 2
|
||||
|
||||
@@ -26,7 +26,7 @@ const OPTIONAL_LIVE_SHARD_FILE_ENVS = new Map([
|
||||
["src/agents/embedded-agent-runner.cache.live.test.ts", ["OPENCLAW_LIVE_CACHE_TEST"]],
|
||||
["src/agents/live-cache-regression.live.test.ts", ["OPENCLAW_LIVE_CACHE_TEST"]],
|
||||
["src/agents/provider-headers.live.test.ts", ["OPENCLAW_LIVE_CACHE_TEST"]],
|
||||
["src/agents/subagent-announce.live.test.ts", ["OPENCLAW_LIVE_SUBAGENT_E2E"]],
|
||||
["src/agents/subagents/announce/subagent-announce.live.test.ts", ["OPENCLAW_LIVE_SUBAGENT_E2E"]],
|
||||
["src/agents/tools/image-tool.ollama.live.test.ts", ["OPENCLAW_LIVE_OLLAMA_IMAGE"]],
|
||||
["src/agents/tools/image-tool.providers.live.test.ts", ["OPENCLAW_LIVE_IMAGE_TOOL_TEST"]],
|
||||
[
|
||||
|
||||
@@ -85,7 +85,7 @@ cd "$tmp_dir"
|
||||
OPENCLAW_LIVE_TEST=1 \
|
||||
OPENCLAW_LIVE_SUBAGENT_E2E=1 \
|
||||
OPENCLAW_VITEST_MAX_WORKERS="${OPENCLAW_VITEST_MAX_WORKERS:-1}" \
|
||||
node --import tsx scripts/test-live.mts -- src/agents/subagent-announce.live.test.ts -- --reporter=verbose
|
||||
node --import tsx scripts/test-live.mts -- src/agents/subagents/announce/subagent-announce.live.test.ts -- --reporter=verbose
|
||||
EOF
|
||||
|
||||
OPENCLAW_LIVE_DOCKER_REPO_ROOT="$ROOT_DIR" "$TRUSTED_HARNESS_DIR/scripts/test-live-build-docker.sh"
|
||||
@@ -98,7 +98,7 @@ if openclaw_live_uses_managed_bind_dirs; then
|
||||
fi
|
||||
|
||||
echo "==> Run subagent announce live test in Docker"
|
||||
echo "==> Target: src/agents/subagent-announce.live.test.ts"
|
||||
echo "==> Target: src/agents/subagents/announce/subagent-announce.live.test.ts"
|
||||
echo "==> Model: ${OPENCLAW_LIVE_SUBAGENT_E2E_MODEL:-openai/gpt-5.6-luna}"
|
||||
echo "==> Profile file: $PROFILE_STATUS"
|
||||
DOCKER_RUN_ARGS=()
|
||||
|
||||
@@ -6,13 +6,13 @@ import { loadSessionEntry, replaceSessionEntry } from "../config/sessions/sessio
|
||||
import { getAgentEventLifecycleGeneration } from "../infra/agent-events.js";
|
||||
import { runWithAgentCommandRecoveryOwner } from "./agent-command-recovery-owner.js";
|
||||
import type { AgentCommandOpts } from "./command/types.js";
|
||||
import { claimMainSessionRecoveryOwner } from "./main-session-recovery-store.js";
|
||||
import { claimMainSessionRecoveryOwner } from "./main-session-recovery/main-session-recovery-store.js";
|
||||
|
||||
const recoveryOwnerMocks = vi.hoisted(() => ({
|
||||
scheduleMainSessionRecoveryPendingTarget: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./main-session-recovery-owner-release.js", () => ({
|
||||
vi.mock("./main-session-recovery/main-session-recovery-owner-release.js", () => ({
|
||||
scheduleMainSessionRecoveryPendingTarget:
|
||||
recoveryOwnerMocks.scheduleMainSessionRecoveryPendingTarget,
|
||||
}));
|
||||
|
||||
@@ -3,8 +3,8 @@ import type { InternalSessionEntry } from "../config/sessions.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import type { AgentCommandOpts } from "./command/types.js";
|
||||
import { repairMainSessionRecoveryMutation } from "./main-session-recovery-lifecycle.js";
|
||||
import { scheduleMainSessionRecoveryPendingTarget } from "./main-session-recovery-owner-release.js";
|
||||
import { repairMainSessionRecoveryMutation } from "./main-session-recovery/main-session-recovery-lifecycle.js";
|
||||
import { scheduleMainSessionRecoveryPendingTarget } from "./main-session-recovery/main-session-recovery-owner-release.js";
|
||||
import {
|
||||
claimMainSessionRecoveryOwner,
|
||||
inspectMainSessionRecoveryRequired,
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
releaseMainSessionRecoveryOwner,
|
||||
type MainSessionRecoveryOwnerLease,
|
||||
type MainSessionRecoveryPendingTarget,
|
||||
} from "./main-session-recovery-store.js";
|
||||
} from "./main-session-recovery/main-session-recovery-store.js";
|
||||
|
||||
const log = createSubsystemLogger("agents/agent-command");
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ vi.mock("./command/types.js", () => ({}));
|
||||
|
||||
// Recovery ownership has dedicated store-backed coverage. This command suite
|
||||
// uses an intentionally synthetic session resolver with no durable store path.
|
||||
vi.mock("./main-session-recovery-store.js", () => ({
|
||||
vi.mock("./main-session-recovery/main-session-recovery-store.js", () => ({
|
||||
claimMainSessionRecoveryOwner: vi.fn(async () => ({ kind: "not_required" })),
|
||||
inspectMainSessionRecoveryRequired: vi.fn(async () => ({ kind: "not_required" })),
|
||||
releaseMainSessionRecoveryOwner: vi.fn(async () => undefined),
|
||||
|
||||
@@ -59,7 +59,7 @@ import {
|
||||
resolveInternalSessionEffectsTarget,
|
||||
} from "./internal-session-effects.js";
|
||||
import { AGENT_LANE_SUBAGENT } from "./lanes.js";
|
||||
import type { MainSessionRecoveryPendingTarget } from "./main-session-recovery-store.js";
|
||||
import type { MainSessionRecoveryPendingTarget } from "./main-session-recovery/main-session-recovery-store.js";
|
||||
import type { AgentRunSessionTarget } from "./run-session-target.js";
|
||||
import { createAgentRunRestartAbortError } from "./run-termination.js";
|
||||
import { measureAgentStartup } from "./startup-timing.js";
|
||||
|
||||
@@ -6,7 +6,10 @@ import {
|
||||
prependAgentSteeringPrompt,
|
||||
releaseLeasedAgentSteeringItemsFromSubagentRuns,
|
||||
} from "./agent-steering-queue.js";
|
||||
import type { PendingFinalDeliveryPayload, SubagentRunRecord } from "./subagent-registry.types.js";
|
||||
import type {
|
||||
PendingFinalDeliveryPayload,
|
||||
SubagentRunRecord,
|
||||
} from "./subagents/registry/subagent-registry.types.js";
|
||||
|
||||
const requesterSessionKey = "agent:main:main";
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import type {
|
||||
PendingFinalDeliveryPayload,
|
||||
SubagentCompletionDeliveryState,
|
||||
SubagentRunRecord,
|
||||
} from "./subagent-registry.types.js";
|
||||
} from "./subagents/registry/subagent-registry.types.js";
|
||||
import { selectDeliverableSessionsReply } from "./tools/sessions-send-tokens.js";
|
||||
|
||||
// Steering queue utilities for delivering completed subagent results back into
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
resolveStoredSubagentCapabilities,
|
||||
type SessionCapabilityStore,
|
||||
type SubagentSessionRole,
|
||||
} from "./subagent-capabilities.js";
|
||||
} from "./subagents/spawn/subagent-capabilities.js";
|
||||
import { isToolAllowedByPolicyName } from "./tool-policy-match.js";
|
||||
import { mergeAlsoAllowPolicy, resolveToolProfilePolicy } from "./tool-policy.js";
|
||||
import { AUTOMATIONS_TOOL_NAME } from "./tools/automations-tool-name.js";
|
||||
|
||||
@@ -77,7 +77,7 @@ import {
|
||||
createReadTool,
|
||||
createWriteTool,
|
||||
} from "./sessions/index.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "./subagent-announce-handoff.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "./subagents/announce/subagent-announce-handoff.js";
|
||||
import { createToolFsPolicy, resolveToolFsConfig } from "./tool-fs-policy.js";
|
||||
import { resolveToolLoopDetectionConfig } from "./tool-loop-detection-config.js";
|
||||
import { buildDeclaredToolAllowlistContext } from "./tool-policy-declared-context.js";
|
||||
|
||||
@@ -11,8 +11,11 @@ import type { CodeModeNamespaceRuntime } from "./code-mode-namespaces.js";
|
||||
import type { PendingBridgeRequest, SettledBridgeRequest } from "./code-mode-runtime.js";
|
||||
import { readCodeModeSkill } from "./code-mode-skills.js";
|
||||
import type { AgentToolUpdateCallback } from "./runtime/index.js";
|
||||
import { getSwarmRunByLaunchReplayKey, initSubagentRegistry } from "./subagent-registry.js";
|
||||
import type { SubagentRunRecord } from "./subagent-registry.types.js";
|
||||
import {
|
||||
getSwarmRunByLaunchReplayKey,
|
||||
initSubagentRegistry,
|
||||
} from "./subagents/registry/subagent-registry.js";
|
||||
import type { SubagentRunRecord } from "./subagents/registry/subagent-registry.types.js";
|
||||
import {
|
||||
SWARM_CODE_MODE_IDEMPOTENCY_KEY,
|
||||
SWARM_CODE_MODE_REQUEST_FINGERPRINT,
|
||||
|
||||
@@ -92,7 +92,7 @@ import { buildUsageWithNoCost } from "../stream-message-shared.js";
|
||||
import {
|
||||
isSubagentAnnounceCompletionHandoff,
|
||||
isTrustedSubagentCompletionHandoffForRun,
|
||||
} from "../subagent-announce-handoff.js";
|
||||
} from "../subagents/announce/subagent-announce-handoff.js";
|
||||
import { isRuntimeToolAllowed, isToolAllowedByPolicies } from "../tool-policy-match.js";
|
||||
import { DEFAULT_MAX_LIVE_TOOL_RESULT_CHARS } from "../tool-result-limits.js";
|
||||
import type { ContextUsage } from "../usage.js";
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
setCliSessionId,
|
||||
} from "../cli-session.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
|
||||
import { clearMainSessionRecoveryAfterAgentRun } from "../main-session-recovery-clear.js";
|
||||
import { clearMainSessionRecoveryAfterAgentRun } from "../main-session-recovery/main-session-recovery-clear.js";
|
||||
import { isCliProvider } from "../model-selection.js";
|
||||
import { deriveSessionTotalTokens, hasNonzeroUsage } from "../usage.js";
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ import { sessionDeliveryChannel } from "../../utils/delivery-context.shared.js";
|
||||
import { listAgentIds, resolveDefaultAgentId } from "../agent-scope.js";
|
||||
import { clearBootstrapSnapshotOnSessionRollover } from "../bootstrap-cache.js";
|
||||
import { clearAllCliSessions } from "../cli-session.js";
|
||||
import { transitionMainSessionRecovery } from "../main-session-recovery-state.js";
|
||||
import { transitionMainSessionRecovery } from "../main-session-recovery/main-session-recovery-state.js";
|
||||
|
||||
/** Resolved command session identity plus backing store metadata. */
|
||||
type SessionResolution = {
|
||||
|
||||
@@ -21,9 +21,9 @@ import type { ExecApprovalContinuationPromptRange } from "../bash-tools.exec-app
|
||||
import type { ExecElevatedDefaults } from "../bash-tools.exec-types.js";
|
||||
import type { BootstrapContextRunKind } from "../bootstrap-mode.js";
|
||||
import type { CliSessionBindingFacts } from "../cli-runner/types.js";
|
||||
import type { MainSessionRecoveryOwnerLease } from "../main-session-recovery-store.js";
|
||||
import type { MainSessionRecoveryOwnerLease } from "../main-session-recovery/main-session-recovery-store.js";
|
||||
import type { ScheduledToolPolicyContext } from "../scheduled-tool-policy.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "../subagent-announce-handoff.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "../subagents/announce/subagent-announce-handoff.js";
|
||||
import type { AgentStreamParams, ClientToolDefinition } from "./shared-types.js";
|
||||
|
||||
/** Image content block for Claude API multimodal messages. */
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
import { pickSandboxToolPolicy } from "./sandbox-tool-policy.js";
|
||||
import type { SandboxToolPolicy } from "./sandbox/types.js";
|
||||
import type { ScheduledToolPolicyContext } from "./scheduled-tool-policy.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "./subagent-announce-handoff.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "./subagents/announce/subagent-announce-handoff.js";
|
||||
import type { PromptMode } from "./system-prompt.types.js";
|
||||
import {
|
||||
collectExplicitAllowlist,
|
||||
|
||||
@@ -15,7 +15,7 @@ import type { SkillSnapshot } from "../../skills/types.js";
|
||||
import type { ExecElevatedDefaults, ExecToolDefaults } from "../bash-tools.exec-types.js";
|
||||
import type { AgentRunSessionTarget } from "../run-session-target.js";
|
||||
import type { AgentRuntimeAuthPlan, AgentRuntimePlan } from "../runtime-plan/types.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "../subagent-announce-handoff.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "../subagents/announce/subagent-announce-handoff.js";
|
||||
|
||||
export type CompactEmbeddedAgentSessionParams = {
|
||||
sessionId: string;
|
||||
|
||||
@@ -36,7 +36,7 @@ vi.mock("../harness/selection.js", () => ({
|
||||
runAgentHarnessSettledTurnFinalization: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../subagent-registry.js", () => ({
|
||||
vi.mock("../subagents/registry/subagent-registry.js", () => ({
|
||||
settleRequesterAfterSessionSpawns: mocks.settleRequesterAfterSessionSpawns,
|
||||
}));
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ const mocks = vi.hoisted(() => ({
|
||||
vi.mock("../logger.js", () => ({
|
||||
log: { debug: mocks.logDebug, error: mocks.logError },
|
||||
}));
|
||||
vi.mock("../../subagent-registry.js", () => ({
|
||||
vi.mock("../../subagents/registry/subagent-registry.js", () => ({
|
||||
settleRequesterAfterSessionSpawns: mocks.settleRequesterAfterSessionSpawns,
|
||||
}));
|
||||
vi.mock("../runs.js", () => ({ clearActiveEmbeddedRun: mocks.clearActiveEmbeddedRun }));
|
||||
|
||||
@@ -27,7 +27,7 @@ import { DEFAULT_CONTEXT_TOKENS } from "../../defaults.js";
|
||||
import type { AgentRuntimePlan } from "../../runtime-plan/types.js";
|
||||
import type { AgentMessage } from "../../runtime/index.js";
|
||||
import type { AgentSession, SessionManager } from "../../sessions/index.js";
|
||||
import { buildActiveSubagentSystemPromptAddition } from "../../subagent-active-context.js";
|
||||
import { buildActiveSubagentSystemPromptAddition } from "../../subagents/registry/subagent-active-context.js";
|
||||
import { resolveTranscriptPolicy, type TranscriptPolicy } from "../../transcript-policy.js";
|
||||
import { getHistoryLimitFromSessionKey, limitHistoryTurns } from "../history.js";
|
||||
import { log } from "../logger.js";
|
||||
|
||||
@@ -29,7 +29,7 @@ import type { AgentSession, SessionManager } from "../../sessions/index.js";
|
||||
import {
|
||||
leasePendingAgentSteeringItems,
|
||||
prependAgentSteeringPrompt,
|
||||
} from "../../subagent-registry.js";
|
||||
} from "../../subagents/registry/subagent-registry.js";
|
||||
import {
|
||||
appendModelIdentitySystemPrompt,
|
||||
buildModelIdentityPromptLine,
|
||||
|
||||
@@ -15,7 +15,7 @@ const mocks = vi.hoisted(() => ({
|
||||
warn: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../subagent-registry.js", () => ({
|
||||
vi.mock("../../subagents/registry/subagent-registry.js", () => ({
|
||||
releasePendingAgentSteeringItems: mocks.releasePendingSteering,
|
||||
}));
|
||||
vi.mock("../google-prompt-cache.js", () => ({
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
buildHeartbeatOutcomeContext,
|
||||
claimHeartbeatOutcomeForRun,
|
||||
} from "../../../infra/heartbeat-outcome-store.js";
|
||||
import { releasePendingAgentSteeringItems } from "../../subagent-registry.js";
|
||||
import { releasePendingAgentSteeringItems } from "../../subagents/registry/subagent-registry.js";
|
||||
import { prepareGooglePromptCacheStreamFn } from "../google-prompt-cache.js";
|
||||
import { log } from "../logger.js";
|
||||
import { resolveEmbeddedAgentApiKey } from "../stream-resolution.js";
|
||||
|
||||
@@ -11,7 +11,7 @@ import { resolveImageSanitizationLimits } from "../../image-sanitization.js";
|
||||
import type { AgentMessage } from "../../runtime/index.js";
|
||||
import type { SandboxContext } from "../../sandbox/types.js";
|
||||
import type { AgentSession } from "../../sessions/index.js";
|
||||
import { ackPendingAgentSteeringItems } from "../../subagent-registry.js";
|
||||
import { ackPendingAgentSteeringItems } from "../../subagents/registry/subagent-registry.js";
|
||||
import { normalizeAssistantReplayContent } from "../replay-history.js";
|
||||
import { updateActiveEmbeddedRunSnapshot } from "../runs.js";
|
||||
import {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
type AgentRunAttemptFailureSource,
|
||||
} from "../../agent-run-terminal-outcome.js";
|
||||
import type { AgentMessage } from "../../runtime/index.js";
|
||||
import { settleRequesterAfterSessionSpawns } from "../../subagent-registry.js";
|
||||
import { settleRequesterAfterSessionSpawns } from "../../subagents/registry/subagent-registry.js";
|
||||
import type { NormalizedUsage } from "../../usage.js";
|
||||
import { log } from "../logger.js";
|
||||
import type { PromptCacheBreak, PromptCacheChange } from "../prompt-cache-observability.js";
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
runAgentHarnessSettledTurnFinalization,
|
||||
} from "../../harness/selection.js";
|
||||
import type { AgentHarness } from "../../harness/types.js";
|
||||
import { settleRequesterAfterSessionSpawns } from "../../subagent-registry.js";
|
||||
import { settleRequesterAfterSessionSpawns } from "../../subagents/registry/subagent-registry.js";
|
||||
import type { EmbeddedRunAttemptParams, EmbeddedRunAttemptResult } from "./types.js";
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,7 +50,7 @@ import type { AgentRunSessionTarget } from "../../run-session-target.js";
|
||||
import type { AgentMessage } from "../../runtime/index.js";
|
||||
import type { ScheduledToolPolicyContext } from "../../scheduled-tool-policy.js";
|
||||
import type { SessionManager } from "../../sessions/index.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "../../subagent-announce-handoff.js";
|
||||
import type { TrustedSubagentCompletionHandoff } from "../../subagents/announce/subagent-announce-handoff.js";
|
||||
import type { SilentReplyPromptMode } from "../../system-prompt.types.js";
|
||||
import type { PromptMode } from "../../system-prompt.types.js";
|
||||
import type { EmbeddedAgentExecutionPhase } from "../execution-phase.js";
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
|
||||
type MainRecoveryStateFields = Pick<
|
||||
SessionEntry,
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import { mergeRestartRecoveryTerminalRunIds } from "../config/sessions/restart-recovery-state.js";
|
||||
import { retryAsync } from "../infra/retry.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import { mergeRestartRecoveryTerminalRunIds } from "../../config/sessions/restart-recovery-state.js";
|
||||
import { retryAsync } from "../../infra/retry.js";
|
||||
import {
|
||||
buildMainSessionRecoveryClearPatch,
|
||||
type MainRecoveryStateFields,
|
||||
+2
-2
@@ -19,5 +19,5 @@ export function scheduleMainSessionRecoveryPendingTarget(
|
||||
() => {}, // Startup recovery remains the fallback if this optional module cannot load.
|
||||
);
|
||||
}
|
||||
import { getRuntimeConfig } from "../config/io.js";
|
||||
import { getGatewayRecoveryRuntime } from "../gateway/server-recovery-runtime-context.js";
|
||||
import { getRuntimeConfig } from "../../config/io.js";
|
||||
import { getGatewayRecoveryRuntime } from "../../gateway/server-recovery-runtime-context.js";
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import { projectMainSessionRecoveryLifecycle } from "./main-session-recovery-lifecycle.js";
|
||||
|
||||
function recoveryEntry(params?: {
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
|
||||
import type {
|
||||
InternalSessionEntry as SessionEntry,
|
||||
MainRestartRecoveryState,
|
||||
} from "../config/sessions.js";
|
||||
} from "../../config/sessions.js";
|
||||
import { transitionMainSessionRecovery } from "./main-session-recovery-state.js";
|
||||
|
||||
const executionIdentity = (runId: string) => ({
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
|
||||
import type {
|
||||
InternalSessionEntry as SessionEntry,
|
||||
MainRestartRecoveryState,
|
||||
} from "../config/sessions.js";
|
||||
} from "../../config/sessions.js";
|
||||
import { buildMainSessionRecoveryClearPatch } from "./main-session-recovery-clear.js";
|
||||
import { projectMainSessionRecoveryLifecycle } from "./main-session-recovery-lifecycle.js";
|
||||
import { transitionMainSessionRecovery } from "./main-session-recovery-state.js";
|
||||
+8
-4
@@ -1,14 +1,18 @@
|
||||
import {
|
||||
PENDING_FINAL_DELIVERY_CLEAR_PATCH,
|
||||
sanitizePendingFinalDeliveryText,
|
||||
} from "../auto-reply/reply/pending-final-delivery.js";
|
||||
} from "../../auto-reply/reply/pending-final-delivery.js";
|
||||
import type {
|
||||
InternalSessionEntry as SessionEntry,
|
||||
MainRestartRecoveryState,
|
||||
RestartRecoveryRun,
|
||||
} from "../config/sessions.js";
|
||||
import { buildRestartRecoveryClaimCleanupPatch } from "../config/sessions/restart-recovery-state.js";
|
||||
import { isAcpSessionKey, isCronSessionKey, isSubagentSessionKey } from "../routing/session-key.js";
|
||||
} from "../../config/sessions.js";
|
||||
import { buildRestartRecoveryClaimCleanupPatch } from "../../config/sessions/restart-recovery-state.js";
|
||||
import {
|
||||
isAcpSessionKey,
|
||||
isCronSessionKey,
|
||||
isSubagentSessionKey,
|
||||
} from "../../routing/session-key.js";
|
||||
import { buildMainSessionRecoveryClearPatch } from "./main-session-recovery-clear.js";
|
||||
import type {
|
||||
MainSessionRecoveryCommand,
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { useAutoCleanupTempDirTracker } from "../../test/helpers/temp-dir.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import * as sessionAccessor from "../config/sessions/session-accessor.js";
|
||||
import { useAutoCleanupTempDirTracker } from "../../../test/helpers/temp-dir.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import * as sessionAccessor from "../../config/sessions/session-accessor.js";
|
||||
import {
|
||||
applySessionEntryLifecycleMutation,
|
||||
listSessionEntries,
|
||||
} from "../config/sessions/session-accessor.js";
|
||||
} from "../../config/sessions/session-accessor.js";
|
||||
import {
|
||||
getAgentEventLifecycleGeneration,
|
||||
rotateAgentEventLifecycleGeneration,
|
||||
} from "../infra/agent-events.js";
|
||||
} from "../../infra/agent-events.js";
|
||||
import {
|
||||
claimMainSessionRecoveryOwner,
|
||||
commitMainSessionRecovery,
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import { applySessionEntryReplacements } from "../config/sessions/session-accessor.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../infra/agent-events.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import { applySessionEntryReplacements } from "../../config/sessions/session-accessor.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../../infra/agent-events.js";
|
||||
import {
|
||||
retryMainSessionRecoveryMutation,
|
||||
scheduleMainSessionRecoveryMutation,
|
||||
+1
-1
@@ -2,7 +2,7 @@ import type {
|
||||
InternalSessionEntry as SessionEntry,
|
||||
MainRestartRecoveryState,
|
||||
RestartRecoveryRun,
|
||||
} from "../config/sessions.js";
|
||||
} from "../../config/sessions.js";
|
||||
|
||||
type MainSessionRecoveryExecutionIdentity = NonNullable<
|
||||
MainRestartRecoveryState["executionIdentity"]
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { SessionEntry } from "../config/sessions.js";
|
||||
import { loadExactSessionEntry } from "../config/sessions/session-accessor.js";
|
||||
import type { SessionEntry } from "../../config/sessions.js";
|
||||
import { loadExactSessionEntry } from "../../config/sessions/session-accessor.js";
|
||||
|
||||
export type ExpectedRestartRecoveryClaim = {
|
||||
canonicalSessionKey?: string;
|
||||
+23
-23
@@ -1,35 +1,36 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { GatewayClientRequestError } from "../../packages/gateway-client/src/index.js";
|
||||
import { isExecutionIdentityCollectionEnabled } from "../audit/audit-config.js";
|
||||
import { createExecutionIdentityAdmissionToken } from "../audit/execution-identity-admission.js";
|
||||
import { sanitizePendingFinalDeliveryText } from "../auto-reply/reply/pending-final-delivery.js";
|
||||
import type { SessionEntry } from "../config/sessions.js";
|
||||
import { GatewayClientRequestError } from "../../../packages/gateway-client/src/index.js";
|
||||
import { isExecutionIdentityCollectionEnabled } from "../../audit/audit-config.js";
|
||||
import { createExecutionIdentityAdmissionToken } from "../../audit/execution-identity-admission.js";
|
||||
import { sanitizePendingFinalDeliveryText } from "../../auto-reply/reply/pending-final-delivery.js";
|
||||
import type { SessionEntry } from "../../config/sessions.js";
|
||||
import {
|
||||
buildRestartRecoveryClaimCleanupPatch,
|
||||
hasRestartRecoveryTerminalRun,
|
||||
resolveRestartRecoveryChannelAuthority,
|
||||
} from "../config/sessions/restart-recovery-state.js";
|
||||
import { applySessionEntryReplacements } from "../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { isTrustedMessageActionTurnIngress } from "../gateway/message-action-turn-capability.js";
|
||||
import type { GatewayRecoveryRuntime } from "../gateway/server-instance-runtime.types.js";
|
||||
import type { AgentRunRequest } from "../gateway/server-methods/agent-request-types.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../infra/agent-events.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { findRestartRecoveryUnsafeReplyHook } from "../plugins/restart-recovery-hook-safety.js";
|
||||
import { withPluginRuntimeRegistryScope } from "../plugins/runtime/gateway-request-scope.js";
|
||||
import { CommandLane } from "../process/lanes.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
||||
import { MAIN_SESSION_RESTART_RECOVERY_SOURCE_TOOL } from "../sessions/input-provenance.js";
|
||||
import { resolveSendPolicy } from "../sessions/send-policy.js";
|
||||
} from "../../config/sessions/restart-recovery-state.js";
|
||||
import { applySessionEntryReplacements } from "../../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { isTrustedMessageActionTurnIngress } from "../../gateway/message-action-turn-capability.js";
|
||||
import type { GatewayRecoveryRuntime } from "../../gateway/server-instance-runtime.types.js";
|
||||
import type { AgentRunRequest } from "../../gateway/server-methods/agent-request-types.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../../infra/agent-events.js";
|
||||
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
||||
import { findRestartRecoveryUnsafeReplyHook } from "../../plugins/restart-recovery-hook-safety.js";
|
||||
import { withPluginRuntimeRegistryScope } from "../../plugins/runtime/gateway-request-scope.js";
|
||||
import { CommandLane } from "../../process/lanes.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||
import { MAIN_SESSION_RESTART_RECOVERY_SOURCE_TOOL } from "../../sessions/input-provenance.js";
|
||||
import { resolveSendPolicy } from "../../sessions/send-policy.js";
|
||||
import {
|
||||
deliveryContextFromSession,
|
||||
normalizeDeliveryContext,
|
||||
type DeliveryContext,
|
||||
} from "../utils/delivery-context.shared.js";
|
||||
import { isDeliverableMessageChannel } from "../utils/message-channel.js";
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "./agent-scope.js";
|
||||
} from "../../utils/delivery-context.shared.js";
|
||||
import { isDeliverableMessageChannel } from "../../utils/message-channel.js";
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent-scope.js";
|
||||
import { loadAgentRuntimePluginRegistryHandle } from "../runtime-plugins.js";
|
||||
import { buildMainSessionRecoveryClearPatch } from "./main-session-recovery-clear.js";
|
||||
import {
|
||||
repairMainSessionRecoveryMutation,
|
||||
@@ -44,7 +45,6 @@ import {
|
||||
} from "./main-session-recovery-state.js";
|
||||
import { commitMainSessionRecovery } from "./main-session-recovery-store.js";
|
||||
import { normalizeFiniteTimestamp } from "./main-session-restart-recovery-shared.js";
|
||||
import { loadAgentRuntimePluginRegistryHandle } from "./runtime-plugins.js";
|
||||
|
||||
const log = createSubsystemLogger("main-session-restart-recovery");
|
||||
const RESTART_RECOVERY_RESUME_MESSAGE =
|
||||
+7
-7
@@ -1,23 +1,23 @@
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import { buildRestartRecoveryClaimCleanupPatch } from "../config/sessions/restart-recovery-state.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import { buildRestartRecoveryClaimCleanupPatch } from "../../config/sessions/restart-recovery-state.js";
|
||||
import {
|
||||
applySessionEntryReplacements,
|
||||
persistSessionTranscriptTurn,
|
||||
type SessionTranscriptTurnLifecyclePatch,
|
||||
updateSessionEntry,
|
||||
} from "../config/sessions/session-accessor.js";
|
||||
} from "../../config/sessions/session-accessor.js";
|
||||
import {
|
||||
hasInterSessionUserProvenance,
|
||||
isCompletionReportInputProvenance,
|
||||
} from "../sessions/input-provenance.js";
|
||||
import { buildRunUserTurnIdempotencyKey } from "../sessions/user-turn-transcript.js";
|
||||
import { isAnnounceRunId } from "./announce-idempotency.js";
|
||||
} from "../../sessions/input-provenance.js";
|
||||
import { buildRunUserTurnIdempotencyKey } from "../../sessions/user-turn-transcript.js";
|
||||
import { isAnnounceRunId } from "../announce-idempotency.js";
|
||||
import {
|
||||
getTranscriptMessageRole as getMessageRole,
|
||||
isTerminalSilentAssistantMessage,
|
||||
readTerminalSourceReplyDeliveryMirror,
|
||||
} from "./embedded-agent-runner/message-visibility.js";
|
||||
} from "../embedded-agent-runner/message-visibility.js";
|
||||
import { buildMainSessionRecoveryClearPatch } from "./main-session-recovery-clear.js";
|
||||
import { isRestartAbortTailArtifact } from "./main-session-restart-recovery-resume-policy.js";
|
||||
import { buildRestartRecoveryExpectedState, log } from "./main-session-restart-recovery-shared.js";
|
||||
+5
-5
@@ -1,8 +1,8 @@
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import { loadSessionEntry } from "../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { GatewayRecoveryRuntime } from "../gateway/server-instance-runtime.types.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import { loadSessionEntry } from "../../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { GatewayRecoveryRuntime } from "../../gateway/server-instance-runtime.types.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||
import type { MainSessionRecoveryObservation } from "./main-session-recovery-state.js";
|
||||
import { commitMainSessionRecovery } from "./main-session-recovery-store.js";
|
||||
import { resolveRestartRecoveryDeliveryContext } from "./main-session-restart-dispatch.js";
|
||||
+9
-9
@@ -1,20 +1,21 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import path from "node:path";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { resolveStateDir } from "../../config/paths.js";
|
||||
import {
|
||||
type InternalSessionEntry as SessionEntry,
|
||||
type RestartRecoveryRun,
|
||||
resolveAllAgentSessionStoreTargetsSync,
|
||||
} from "../config/sessions.js";
|
||||
import { applySessionEntryReplacements } from "../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { resolveGatewaySessionStoreTarget } from "../gateway/session-utils.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../infra/agent-events.js";
|
||||
import { listAgentRunsForSession } from "../infra/agent-run-registry.js";
|
||||
} from "../../config/sessions.js";
|
||||
import { applySessionEntryReplacements } from "../../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { resolveGatewaySessionStoreTarget } from "../../gateway/session-utils.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../../infra/agent-events.js";
|
||||
import { listAgentRunsForSession } from "../../infra/agent-run-registry.js";
|
||||
import {
|
||||
listActiveEmbeddedRunSessionIds,
|
||||
listActiveEmbeddedRunSessionKeys,
|
||||
} from "./embedded-agent-runner/run-state.js";
|
||||
} from "../embedded-agent-runner/run-state.js";
|
||||
import { resolveAgentSessionDirs } from "../session-dirs.js";
|
||||
import {
|
||||
isMainRestartRecoveryCandidate,
|
||||
normalizeMainSessionRecoveryRunFences,
|
||||
@@ -27,7 +28,6 @@ import {
|
||||
normalizeStringSet,
|
||||
resolveRestartRecoveryStorePaths,
|
||||
} from "./main-session-restart-recovery-shared.js";
|
||||
import { resolveAgentSessionDirs } from "./session-dirs.js";
|
||||
|
||||
async function markRecoveryStore(params: {
|
||||
storePath: string;
|
||||
+8
-8
@@ -1,14 +1,14 @@
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import type {
|
||||
SessionTranscriptTurnExpectedState,
|
||||
SessionTranscriptTurnLifecyclePatch,
|
||||
} from "../config/sessions/session-accessor.js";
|
||||
import { appendAssistantMessageToSessionTranscript } from "../config/sessions/transcript.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { GatewayRecoveryRuntime } from "../gateway/server-instance-runtime.types.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
||||
import type { DeliveryContext } from "../utils/delivery-context.shared.js";
|
||||
import { resolveDefaultAgentId } from "./agent-scope-config.js";
|
||||
} from "../../config/sessions/session-accessor.js";
|
||||
import { appendAssistantMessageToSessionTranscript } from "../../config/sessions/transcript.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { GatewayRecoveryRuntime } from "../../gateway/server-instance-runtime.types.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||
import type { DeliveryContext } from "../../utils/delivery-context.shared.js";
|
||||
import { resolveDefaultAgentId } from "../agent-scope-config.js";
|
||||
import type { MainSessionRecoveryObservation } from "./main-session-recovery-state.js";
|
||||
import { commitMainSessionRecovery } from "./main-session-recovery-store.js";
|
||||
import { buildUnresumableSessionNoticeIdempotencyKey } from "./main-session-restart-claim.js";
|
||||
+3
-3
@@ -1,16 +1,16 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { resolveMainSessionResumePolicy } from "./main-session-restart-recovery-resume-policy.js";
|
||||
|
||||
vi.mock("./code-mode-control-tools.js", () => ({
|
||||
vi.mock("../code-mode-control-tools.js", () => ({
|
||||
CODE_MODE_EXEC_TOOL_NAME: "exec",
|
||||
CODE_MODE_WAIT_TOOL_NAME: "wait",
|
||||
}));
|
||||
|
||||
vi.mock("./tool-replay-safety.js", () => ({
|
||||
vi.mock("../tool-replay-safety.js", () => ({
|
||||
isAgentToolReplaySafe: ({ name }: { name?: string }) => name === "read",
|
||||
}));
|
||||
|
||||
vi.mock("./run-termination.js", () => ({
|
||||
vi.mock("../run-termination.js", () => ({
|
||||
AGENT_RUN_RESTART_ABORT_ERROR: "agent run aborted for restart",
|
||||
AGENT_RUN_RESTART_ABORT_ERROR_CODE: "OPENCLAW_RESTART_ABORT",
|
||||
}));
|
||||
+5
-5
@@ -1,17 +1,17 @@
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import { CODE_MODE_EXEC_TOOL_NAME, CODE_MODE_WAIT_TOOL_NAME } from "./code-mode-control-tools.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import { CODE_MODE_EXEC_TOOL_NAME, CODE_MODE_WAIT_TOOL_NAME } from "../code-mode-control-tools.js";
|
||||
import {
|
||||
getTranscriptMessageRole as getMessageRole,
|
||||
isIntermediateAssistantTranscriptMessage,
|
||||
isMeaningfulTranscriptMessage,
|
||||
readTerminalSourceReplyDeliveryMirror,
|
||||
} from "./embedded-agent-runner/message-visibility.js";
|
||||
} from "../embedded-agent-runner/message-visibility.js";
|
||||
import {
|
||||
AGENT_RUN_RESTART_ABORT_ERROR,
|
||||
AGENT_RUN_RESTART_ABORT_ERROR_CODE,
|
||||
} from "./run-termination.js";
|
||||
import { isAgentToolReplaySafe } from "./tool-replay-safety.js";
|
||||
} from "../run-termination.js";
|
||||
import { isAgentToolReplaySafe } from "../tool-replay-safety.js";
|
||||
|
||||
function readDeliveredTerminalSourceReplyToolCallId(
|
||||
messages: readonly unknown[],
|
||||
+6
-6
@@ -1,15 +1,15 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { GatewayRecoveryRuntime } from "../gateway/server-instance-runtime.types.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { GatewayRecoveryRuntime } from "../../gateway/server-instance-runtime.types.js";
|
||||
import {
|
||||
getAgentEventLifecycleGeneration,
|
||||
isAgentEventLifecycleGenerationCurrent,
|
||||
} from "../infra/agent-events.js";
|
||||
import { sleepWithAbort } from "../infra/backoff.js";
|
||||
import { runWithGatewayIndependentRootWorkAdmission } from "../process/gateway-work-admission.js";
|
||||
} from "../../infra/agent-events.js";
|
||||
import { sleepWithAbort } from "../../infra/backoff.js";
|
||||
import { runWithGatewayIndependentRootWorkAdmission } from "../../process/gateway-work-admission.js";
|
||||
import {
|
||||
beginSessionWorkAdmission,
|
||||
cancelSessionWorkAdmissionHandoff,
|
||||
} from "../sessions/session-lifecycle-admission.js";
|
||||
} from "../../sessions/session-lifecycle-admission.js";
|
||||
import {
|
||||
loadExpectedRestartRecoveryClaim,
|
||||
type ExpectedRestartRecoveryClaim,
|
||||
+6
-6
@@ -1,18 +1,18 @@
|
||||
import path from "node:path";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { resolveStateDir } from "../../config/paths.js";
|
||||
import {
|
||||
listConfiguredSessionStoreAgentIds,
|
||||
resolveStorePath,
|
||||
type InternalSessionEntry as SessionEntry,
|
||||
resolveAllAgentSessionStoreTargetsSync,
|
||||
} from "../config/sessions.js";
|
||||
} from "../../config/sessions.js";
|
||||
import {
|
||||
hasSessionEntriesByStatusReadOnly,
|
||||
type SessionTranscriptTurnExpectedState,
|
||||
} from "../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { resolveAgentSessionDirs } from "./session-dirs.js";
|
||||
} from "../../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
||||
import { resolveAgentSessionDirs } from "../session-dirs.js";
|
||||
|
||||
export const log = createSubsystemLogger("main-session-restart-recovery");
|
||||
export const DEFAULT_RECOVERY_DELAY_MS = 5_000;
|
||||
+10
-10
@@ -4,22 +4,22 @@ import { normalizeOptionalString } from "@openclaw/normalization-core/string-coe
|
||||
import {
|
||||
type InternalSessionEntry as SessionEntry,
|
||||
resolveSessionWorkStartError,
|
||||
} from "../config/sessions.js";
|
||||
} from "../../config/sessions.js";
|
||||
import {
|
||||
listSessionEntriesByStatus,
|
||||
loadExactSessionEntry,
|
||||
} from "../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { GatewayRecoveryRuntime } from "../gateway/server-instance-runtime.types.js";
|
||||
import { readSessionMessagesAsync } from "../gateway/session-transcript-readers.js";
|
||||
import { resolveGatewaySessionStoreTarget } from "../gateway/session-utils.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../infra/agent-events.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
||||
import { resolveDefaultAgentId } from "./agent-scope-config.js";
|
||||
} from "../../config/sessions/session-accessor.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { GatewayRecoveryRuntime } from "../../gateway/server-instance-runtime.types.js";
|
||||
import { readSessionMessagesAsync } from "../../gateway/session-transcript-readers.js";
|
||||
import { resolveGatewaySessionStoreTarget } from "../../gateway/session-utils.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../../infra/agent-events.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||
import { resolveDefaultAgentId } from "../agent-scope-config.js";
|
||||
import {
|
||||
listActiveEmbeddedRunSessionIds,
|
||||
listActiveEmbeddedRunSessionKeys,
|
||||
} from "./embedded-agent-runner/run-state.js";
|
||||
} from "../embedded-agent-runner/run-state.js";
|
||||
import { isMainRestartRecoveryCandidate } from "./main-session-recovery-state.js";
|
||||
import { commitMainSessionRecovery } from "./main-session-recovery-store.js";
|
||||
import {
|
||||
+43
-43
@@ -3,66 +3,76 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { GatewayClientRequestError } from "../../packages/gateway-client/src/index.js";
|
||||
import { createDeferred } from "../../test/helpers/promise.js";
|
||||
import { markInboundContextLabel } from "../auto-reply/reply/inbound-context-marker.js";
|
||||
import type { ChannelOutboundAdapter } from "../channels/plugins/types.public.js";
|
||||
import type { CliDeps } from "../cli/outbound-send-deps.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../config/sessions.js";
|
||||
import * as sessionAccessor from "../config/sessions/session-accessor.js";
|
||||
import { GatewayClientRequestError } from "../../../packages/gateway-client/src/index.js";
|
||||
import { createDeferred } from "../../../test/helpers/promise.js";
|
||||
import { markInboundContextLabel } from "../../auto-reply/reply/inbound-context-marker.js";
|
||||
import type { ChannelOutboundAdapter } from "../../channels/plugins/types.public.js";
|
||||
import type { CliDeps } from "../../cli/outbound-send-deps.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { InternalSessionEntry as SessionEntry } from "../../config/sessions.js";
|
||||
import * as sessionAccessor from "../../config/sessions/session-accessor.js";
|
||||
import {
|
||||
appendTranscriptMessage,
|
||||
listSessionEntries,
|
||||
loadSessionEntry as loadSessionEntryRaw,
|
||||
loadTranscriptEvents,
|
||||
replaceSessionEntry,
|
||||
} from "../config/sessions/session-accessor.js";
|
||||
import { callGateway } from "../gateway/call.js";
|
||||
import type { GatewayRecoveryRuntime } from "../gateway/server-instance-runtime.types.js";
|
||||
} from "../../config/sessions/session-accessor.js";
|
||||
import { callGateway } from "../../gateway/call.js";
|
||||
import type { GatewayRecoveryRuntime } from "../../gateway/server-instance-runtime.types.js";
|
||||
import {
|
||||
getAgentEventLifecycleGeneration,
|
||||
resetAgentEventsForTest,
|
||||
rotateAgentEventLifecycleGeneration,
|
||||
} from "../infra/agent-events.js";
|
||||
import { registerAgentRunContext } from "../infra/agent-run-registry.js";
|
||||
} from "../../infra/agent-events.js";
|
||||
import { registerAgentRunContext } from "../../infra/agent-run-registry.js";
|
||||
import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../plugins/hook-runner-global.js";
|
||||
import { addTestHook } from "../plugins/hooks.test-fixtures.js";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { getPluginRuntimeGatewayRequestScope } from "../plugins/runtime/gateway-request-scope.js";
|
||||
} from "../../plugins/hook-runner-global.js";
|
||||
import { addTestHook } from "../../plugins/hooks.test-fixtures.js";
|
||||
import { createEmptyPluginRegistry } from "../../plugins/registry-empty.js";
|
||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
import { getPluginRuntimeGatewayRequestScope } from "../../plugins/runtime/gateway-request-scope.js";
|
||||
import {
|
||||
getActiveGatewayRootWorkCount,
|
||||
resetGatewayWorkAdmission,
|
||||
tryBeginGatewaySuspendAdmission,
|
||||
} from "../process/gateway-work-admission.js";
|
||||
} from "../../process/gateway-work-admission.js";
|
||||
import {
|
||||
interruptSessionWorkAdmissions,
|
||||
isSessionLifecycleMutationActive,
|
||||
isSessionWorkAdmissionActive,
|
||||
runExclusiveSessionLifecycleMutation,
|
||||
} from "../sessions/session-lifecycle-admission.js";
|
||||
} from "../../sessions/session-lifecycle-admission.js";
|
||||
import {
|
||||
closeOpenClawAgentDatabasesForTest,
|
||||
openOpenClawAgentDatabase,
|
||||
} from "../state/openclaw-agent-db.js";
|
||||
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
|
||||
import { createOutboundTestPlugin, createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||
import { normalizeSessionDeliveryState } from "../utils/delivery-context.shared.js";
|
||||
import { deliverAgentCommandResult } from "./command/delivery.js";
|
||||
import { setActiveEmbeddedRunLifecycleGeneration } from "./embedded-agent-runner/run-state.js";
|
||||
} from "../../state/openclaw-agent-db.js";
|
||||
import { closeOpenClawStateDatabaseForTest } from "../../state/openclaw-state-db.js";
|
||||
import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js";
|
||||
import { normalizeSessionDeliveryState } from "../../utils/delivery-context.shared.js";
|
||||
import { deliverAgentCommandResult } from "../command/delivery.js";
|
||||
import { setActiveEmbeddedRunLifecycleGeneration } from "../embedded-agent-runner/run-state.js";
|
||||
import {
|
||||
clearActiveEmbeddedRun,
|
||||
setActiveEmbeddedRun,
|
||||
type EmbeddedAgentQueueHandle,
|
||||
} from "./embedded-agent-runner/runs.js";
|
||||
} from "../embedded-agent-runner/runs.js";
|
||||
import {
|
||||
INTERNAL_RUNTIME_CONTEXT_BEGIN,
|
||||
INTERNAL_RUNTIME_CONTEXT_END,
|
||||
} from "./internal-runtime-context.js";
|
||||
} from "../internal-runtime-context.js";
|
||||
import { AGENT_RUN_RESTART_ABORT_ERROR_CODE } from "../run-termination.js";
|
||||
import {
|
||||
createAssistantToolCallMessage,
|
||||
createSessionEntry,
|
||||
createSessionStore,
|
||||
type SessionEntryFixture,
|
||||
expectRecord,
|
||||
mockCallArg,
|
||||
waitForFast,
|
||||
} from "../subagent-test-fixtures.test-helpers.js";
|
||||
import * as recoveryOwnerRelease from "./main-session-recovery-owner-release.js";
|
||||
import { claimMainSessionRecoveryOwner } from "./main-session-recovery-store.js";
|
||||
import { resolveRestartRecoveryStorePaths } from "./main-session-restart-recovery-shared.js";
|
||||
@@ -74,16 +84,6 @@ import {
|
||||
scheduleRestartAbortedMainSessionRecoveryAfterOwnerRelease,
|
||||
scheduleRestartAbortedMainSessionRecovery as scheduleRestartAbortedMainSessionRecoveryBase,
|
||||
} from "./main-session-restart-recovery.js";
|
||||
import { AGENT_RUN_RESTART_ABORT_ERROR_CODE } from "./run-termination.js";
|
||||
import {
|
||||
createAssistantToolCallMessage,
|
||||
createSessionEntry,
|
||||
createSessionStore,
|
||||
type SessionEntryFixture,
|
||||
expectRecord,
|
||||
mockCallArg,
|
||||
waitForFast,
|
||||
} from "./subagent-test-fixtures.test-helpers.js";
|
||||
|
||||
const transcriptMocks = vi.hoisted(() => ({
|
||||
appendAssistantMessageToSessionTranscript: vi.fn(),
|
||||
@@ -101,7 +101,7 @@ const executionIdentityEnabledConfig = {
|
||||
logging: { audit: { executionIdentity: true } },
|
||||
} satisfies OpenClawConfig;
|
||||
|
||||
vi.mock("../gateway/call.js", () => ({
|
||||
vi.mock("../../gateway/call.js", () => ({
|
||||
callGateway: vi.fn(async () => ({ runId: "run-resumed" })),
|
||||
}));
|
||||
|
||||
@@ -144,8 +144,8 @@ function gatewayParams(): Record<string, unknown> {
|
||||
return expectRecord(mockCallArg(callGateway).params, "gateway params");
|
||||
}
|
||||
|
||||
vi.mock("../config/sessions/transcript.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/sessions/transcript.js")>();
|
||||
vi.mock("../../config/sessions/transcript.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../config/sessions/transcript.js")>();
|
||||
transcriptMocks.appendAssistantMessageToSessionTranscript.mockImplementation(
|
||||
actual.appendAssistantMessageToSessionTranscript,
|
||||
);
|
||||
@@ -156,11 +156,11 @@ vi.mock("../config/sessions/transcript.js", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/restart-recovery-hook-safety.js", () => ({
|
||||
vi.mock("../../plugins/restart-recovery-hook-safety.js", () => ({
|
||||
findRestartRecoveryUnsafeReplyHook: runtimePluginMocks.findRestartRecoveryUnsafeReplyHook,
|
||||
}));
|
||||
|
||||
vi.mock("./runtime-plugins.js", () => ({
|
||||
vi.mock("../runtime-plugins.js", () => ({
|
||||
loadAgentRuntimePluginRegistryHandle: runtimePluginMocks.loadAgentRuntimePluginRegistryHandle,
|
||||
}));
|
||||
|
||||
@@ -529,7 +529,7 @@ describe("sessions_yield completion ownership", () => {
|
||||
["the controller when the run owner is blank", " ", controllerSessionKey],
|
||||
["the controller when the run owner is absent", undefined, controllerSessionKey],
|
||||
] as const)("records yield intent against %s", async (_, runSessionKey, expectedSessionKey) => {
|
||||
const registry = await import("./subagent-registry.js");
|
||||
const registry = await import("./subagents/registry/subagent-registry.js");
|
||||
const markRequesterTurnYielded = vi
|
||||
.spyOn(registry, "markRequesterTurnYielded")
|
||||
.mockReturnValue(1);
|
||||
|
||||
@@ -25,7 +25,7 @@ vi.mock("../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => callGatewayMock(opts),
|
||||
}));
|
||||
const loadSessionEntryByKeyMock = vi.fn();
|
||||
vi.mock("./subagent-announce-delivery.js", () => ({
|
||||
vi.mock("./subagents/announce/subagent-announce-delivery.js", () => ({
|
||||
loadSessionEntryByKey: (sessionKey: string) => loadSessionEntryByKeyMock(sessionKey),
|
||||
}));
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
import {
|
||||
addSubagentRunForTests,
|
||||
resetSubagentRegistryForTests,
|
||||
} from "./subagent-registry.test-helpers.js";
|
||||
} from "./subagents/registry/subagent-registry.test-helpers.js";
|
||||
import { createPerSenderSessionConfig } from "./test-helpers/session-config.js";
|
||||
import { createSubagentsTool } from "./tools/subagents-tool.js";
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ const hoisted = vi.hoisted(() => ({
|
||||
configOverride: {} as Record<string, unknown>,
|
||||
}));
|
||||
|
||||
let resetSubagentRegistryForTests: typeof import("./subagent-registry.test-helpers.js").resetSubagentRegistryForTests;
|
||||
let resetSubagentRegistryForTests: typeof import("./subagents/registry/subagent-registry.test-helpers.js").resetSubagentRegistryForTests;
|
||||
let spawnSubagentDirect: typeof import("./subagents/spawn/subagent-spawn.js").spawnSubagentDirect;
|
||||
|
||||
function resolveAgentConfigFromList(cfg: Record<string, unknown>, agentId: string) {
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import {
|
||||
getLatestSubagentRunByChildSessionKey,
|
||||
resetSubagentRegistryForTests,
|
||||
} from "./subagent-registry.test-helpers.js";
|
||||
} from "./subagents/registry/subagent-registry.test-helpers.js";
|
||||
|
||||
const fastModeEnv = vi.hoisted(() => {
|
||||
const previous = process.env.OPENCLAW_TEST_FAST;
|
||||
|
||||
@@ -2,18 +2,20 @@
|
||||
import { vi, type Mock } from "vitest";
|
||||
import type { SessionRunStatus } from "../../packages/gateway-protocol/src/schema/sessions-row.js";
|
||||
import type { SubagentLifecycleHookRunner } from "../plugins/hooks.js";
|
||||
import { resolveRequesterStoreKey } from "./subagent-requester-store-key.js";
|
||||
import { resolveRequesterStoreKey } from "./subagents/announce/subagent-requester-store-key.js";
|
||||
|
||||
type SessionsSpawnTestConfig = ReturnType<
|
||||
(typeof import("../config/config.js"))["getRuntimeConfig"]
|
||||
>;
|
||||
type SessionsSpawnHookRunner = SubagentLifecycleHookRunner | null;
|
||||
type CaptureSubagentCompletionReply =
|
||||
(typeof import("./subagent-announce.js"))["captureSubagentCompletionReply"];
|
||||
type RunSubagentAnnounceFlow = (typeof import("./subagent-announce.js"))["runSubagentAnnounceFlow"];
|
||||
(typeof import("./subagents/announce/subagent-announce.js"))["captureSubagentCompletionReply"];
|
||||
type RunSubagentAnnounceFlow =
|
||||
(typeof import("./subagents/announce/subagent-announce.js"))["runSubagentAnnounceFlow"];
|
||||
type CreateSessionsSpawnTool =
|
||||
(typeof import("./tools/sessions-spawn-tool.js"))["createSessionsSpawnTool"];
|
||||
type SubagentRegistryTesting = (typeof import("./subagent-registry.test-helpers.js"))["testing"];
|
||||
type SubagentRegistryTesting =
|
||||
(typeof import("./subagents/registry/subagent-registry.test-helpers.js"))["testing"];
|
||||
type SubagentSpawnTesting =
|
||||
(typeof import("./subagents/spawn/subagent-spawn.test-support.js"))["testing"];
|
||||
type CreateOpenClawToolsOpts = Parameters<CreateSessionsSpawnTool>[0];
|
||||
@@ -196,7 +198,7 @@ export async function getSessionsSpawnTool(opts: CreateOpenClawToolsOpts) {
|
||||
const [{ testing: subagentSpawnTesting }, { testing: subagentRegistryTesting }] =
|
||||
await Promise.all([
|
||||
import("./subagents/spawn/subagent-spawn.test-support.js"),
|
||||
import("./subagent-registry.test-helpers.js"),
|
||||
import("./subagents/registry/subagent-registry.test-helpers.js"),
|
||||
]);
|
||||
cachedSubagentSpawnTesting = subagentSpawnTesting;
|
||||
cachedSubagentRegistryTesting = subagentRegistryTesting;
|
||||
|
||||
@@ -3,8 +3,8 @@ import { vi } from "vitest";
|
||||
import { testing as queueCleanupTesting } from "../auto-reply/reply/queue/cleanup.test-support.js";
|
||||
import type { CallGatewayOptions } from "../gateway/call.js";
|
||||
import type { MockFn } from "../test-utils/vitest-mock-fn.js";
|
||||
import { testing as subagentAnnounceTesting } from "./subagent-announce.js";
|
||||
import { testing as subagentControlTesting } from "./subagent-control.test-support.js";
|
||||
import { testing as subagentAnnounceTesting } from "./subagents/announce/subagent-announce.js";
|
||||
import { testing as subagentControlTesting } from "./subagents/registry/subagent-control.test-support.js";
|
||||
|
||||
type LoadedConfig = ReturnType<(typeof import("../config/config.js"))["getRuntimeConfig"]>;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
getLatestSubagentRunByChildSessionKey,
|
||||
getSubagentRunByRunId,
|
||||
recordSwarmStructuredOutput,
|
||||
} from "./subagent-registry.js";
|
||||
} from "./subagents/registry/subagent-registry.js";
|
||||
import { resolveSwarmConfig } from "./subagents/swarm/swarm-config.js";
|
||||
import { createAgentsWaitTool } from "./tools/agents-wait-tool.js";
|
||||
import type { AnyAgentTool } from "./tools/common.js";
|
||||
|
||||
@@ -691,7 +691,8 @@ export function createOpenClawTools(
|
||||
onBeforeYield:
|
||||
requesterSessionKey && requesterTurnRunId
|
||||
? async () => {
|
||||
const { markRequesterTurnYielded } = await import("./subagent-registry.js");
|
||||
const { markRequesterTurnYielded } =
|
||||
await import("./subagents/registry/subagent-registry.js");
|
||||
markRequesterTurnYielded({ requesterSessionKey, requesterTurnRunId });
|
||||
}
|
||||
: undefined,
|
||||
|
||||
@@ -16,14 +16,14 @@ import { resolveSenderToolPolicy } from "./sender-tool-policy.js";
|
||||
import {
|
||||
isTrustedSubagentCompletionHandoffForRun,
|
||||
type TrustedSubagentCompletionHandoff,
|
||||
} from "./subagent-announce-handoff.js";
|
||||
} from "./subagents/announce/subagent-announce-handoff.js";
|
||||
import { resolveRequesterStoreKey } from "./subagents/announce/subagent-requester-store-key.js";
|
||||
import {
|
||||
isSubagentEnvelopeSession,
|
||||
resolvePersistedSubagentToolPolicyEnvelope,
|
||||
resolveSubagentCapabilityStore,
|
||||
type SessionCapabilityStore,
|
||||
} from "./subagent-capabilities.js";
|
||||
import { resolveRequesterStoreKey } from "./subagent-requester-store-key.js";
|
||||
} from "./subagents/spawn/subagent-capabilities.js";
|
||||
|
||||
const MAX_DELEGATION_LINEAGE_DEPTH = 32;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { failTransportStream, finalizeTransportStream } from "@openclaw/ai/transports";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { resolveMainSessionResumePolicy } from "./main-session-restart-recovery-resume-policy.js";
|
||||
import { resolveMainSessionResumePolicy } from "./main-session-recovery/main-session-restart-recovery-resume-policy.js";
|
||||
import {
|
||||
createAssistantOutput,
|
||||
makeCompletionsModel,
|
||||
|
||||
@@ -56,7 +56,7 @@ const bindingMocks = vi.hoisted(() => ({
|
||||
listBySession: vi.fn(() => []),
|
||||
}));
|
||||
|
||||
let resetSubagentRegistryForTests: typeof import("./subagent-registry.test-helpers.js").resetSubagentRegistryForTests;
|
||||
let resetSubagentRegistryForTests: typeof import("./subagents/registry/subagent-registry.test-helpers.js").resetSubagentRegistryForTests;
|
||||
let spawnSubagentDirect: typeof import("./subagents/spawn/subagent-spawn.js").spawnSubagentDirect;
|
||||
|
||||
function getGatewayRequests(): GatewayRequest[] {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { SubagentLifecycleHookRunner } from "../plugins/hooks.js";
|
||||
import { registerSubagentRun } from "./subagent-registry.js";
|
||||
import { registerSubagentRun } from "./subagents/registry/subagent-registry.js";
|
||||
|
||||
type SpawnPipelinePhase = "initialize" | "dispatch" | "register";
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { getSessionBindingService } from "../infra/outbound/session-binding-service.js";
|
||||
import { resolveAgentConfig } from "./agent-scope.js";
|
||||
import { resolveChildAdmission, type ChildAdmissionCap } from "./child-admission.js";
|
||||
import { resolveSubagentCapabilities } from "./subagent-capabilities.js";
|
||||
import { getSubagentDepthFromSessionStore } from "./subagent-depth.js";
|
||||
import { countActiveRunsForSession } from "./subagent-registry.js";
|
||||
import { resolveSubagentTargetPolicy } from "./subagent-target-policy.js";
|
||||
import { countActiveRunsForSession } from "./subagents/registry/subagent-registry.js";
|
||||
import { resolveSubagentCapabilities } from "./subagents/spawn/subagent-capabilities.js";
|
||||
import { getSubagentDepthFromSessionStore } from "./subagents/spawn/subagent-depth.js";
|
||||
import { resolveSubagentTargetPolicy } from "./subagents/spawn/subagent-target-policy.js";
|
||||
|
||||
type SpawnMode = "run" | "session";
|
||||
type SpawnBackendKind = "subagent" | "acp";
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Runtime dependency barrel for subagent announcement delivery.
|
||||
*
|
||||
* Tests mock this module to isolate delivery logic from gateway, outbound
|
||||
* message routing, queue settings, hooks, and embedded-run state.
|
||||
*/
|
||||
export { getRuntimeConfig } from "../config/config.js";
|
||||
export { resolveAgentIdFromSessionKey, resolveStorePath } from "../config/sessions.js";
|
||||
export { loadSessionEntryReadOnly as loadSessionEntry } from "../config/sessions/session-accessor.js";
|
||||
export { callGateway } from "../gateway/call.js";
|
||||
export { dispatchGatewayMethodInProcess } from "../gateway/server-plugins.js";
|
||||
export { resolveQueueSettings } from "../auto-reply/reply/queue.js";
|
||||
export { resolveExternalBestEffortDeliveryTarget } from "../infra/outbound/best-effort-delivery.js";
|
||||
export { sendMessage } from "../infra/outbound/message.js";
|
||||
export { createBoundDeliveryRouter } from "../infra/outbound/bound-delivery-router.js";
|
||||
export { resolveConversationIdFromTargets } from "../infra/outbound/conversation-id.js";
|
||||
export { getGlobalHookRunner } from "../plugins/hook-runner-global.js";
|
||||
export {
|
||||
formatEmbeddedAgentQueueFailureSummary,
|
||||
isEmbeddedAgentRunActive,
|
||||
isEmbeddedRunAbandoned,
|
||||
queueEmbeddedAgentMessageWithOutcomeAsync,
|
||||
resolveActiveEmbeddedRunSessionId,
|
||||
} from "./embedded-agent-runner/runs.js";
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Runtime seams used by subagent control for queue and embedded-run cancellation.
|
||||
*/
|
||||
export { clearSessionQueues } from "../auto-reply/reply/queue.js";
|
||||
export { abortEmbeddedAgentRun, isEmbeddedAgentRunActive } from "./embedded-agent-runner/runs.js";
|
||||
@@ -23,15 +23,19 @@ import {
|
||||
} from "../tasks/task-runtime.test-helpers.js";
|
||||
import { captureEnv } from "../test-utils/env.js";
|
||||
import { cleanupSessionStateForTest } from "../test-utils/session-state-cleanup.js";
|
||||
import { subagentRuns } from "./subagent-registry-memory.js";
|
||||
import { persistSubagentRunsToDiskOrThrow } from "./subagent-registry-state.js";
|
||||
import {
|
||||
createSubagentRunRecord,
|
||||
type SubagentRunRecordOverrides,
|
||||
} from "./subagent-test-fixtures.test-helpers.js";
|
||||
import { subagentRuns } from "./subagents/registry/subagent-registry-memory.js";
|
||||
import { persistSubagentRunsToDiskOrThrow } from "./subagents/registry/subagent-registry-state.js";
|
||||
import {
|
||||
createCanonicalSubagentRunFixture,
|
||||
createSubagentRegistryTestDeps,
|
||||
readSubagentSessionStore,
|
||||
writeSubagentSessionEntry,
|
||||
} from "./subagent-registry.persistence.test-support.js";
|
||||
import { loadSubagentRegistryFromSqlite } from "./subagent-registry.store.sqlite.js";
|
||||
} from "./subagents/registry/subagent-registry.persistence.test-support.js";
|
||||
import { loadSubagentRegistryFromSqlite } from "./subagents/registry/subagent-registry.store.sqlite.js";
|
||||
import {
|
||||
addSubagentRunForTests,
|
||||
getSubagentRunByChildSessionKey,
|
||||
@@ -39,12 +43,8 @@ import {
|
||||
listSubagentRunsForRequester,
|
||||
resetSubagentRegistryForTests,
|
||||
testing,
|
||||
} from "./subagent-registry.test-helpers.js";
|
||||
import type { SubagentRunRecord } from "./subagent-registry.types.js";
|
||||
import {
|
||||
createSubagentRunRecord,
|
||||
type SubagentRunRecordOverrides,
|
||||
} from "./subagent-test-fixtures.test-helpers.js";
|
||||
} from "./subagents/registry/subagent-registry.test-helpers.js";
|
||||
import type { SubagentRunRecord } from "./subagents/registry/subagent-registry.types.js";
|
||||
|
||||
function consumeRecoveryAdmission(payload: Record<string, unknown>): SessionWorkAdmissionLease {
|
||||
const sessionKey = String(payload.sessionKey);
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Runtime seams used by subagent registry code for plugin/context-engine initialization.
|
||||
*/
|
||||
export { ensureContextEnginesInitialized } from "../context-engine/init.js";
|
||||
export { resolveContextEngine } from "../context-engine/registry.js";
|
||||
@@ -4,8 +4,8 @@ import type { SessionOrigin } from "../config/sessions/types.js";
|
||||
import { normalizeLegacySessionEntryDelivery } from "../infra/state-migrations.legacy-session-store.js";
|
||||
import type { DeliveryContext } from "../utils/delivery-context.types.js";
|
||||
import type { AgentInternalEvent } from "./internal-events.js";
|
||||
import type { RegisterSubagentRunParams } from "./subagent-registry-run-manager.js";
|
||||
import type { SubagentRunRecord } from "./subagent-registry.types.js";
|
||||
import type { RegisterSubagentRunParams } from "./subagents/registry/subagent-registry-run-manager.js";
|
||||
import type { SubagentRunRecord } from "./subagents/registry/subagent-registry.types.js";
|
||||
|
||||
type GatewayRequest = { method?: string };
|
||||
type GatewayResponse<TRequest, TResult> =
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Runtime dependency barrel for subagent announcement delivery.
|
||||
*
|
||||
* Tests mock this module to isolate delivery logic from gateway, outbound
|
||||
* message routing, queue settings, hooks, and embedded-run state.
|
||||
*/
|
||||
export { getRuntimeConfig } from "../../../config/config.js";
|
||||
export { resolveAgentIdFromSessionKey, resolveStorePath } from "../../../config/sessions.js";
|
||||
export { loadSessionEntryReadOnly as loadSessionEntry } from "../../../config/sessions/session-accessor.js";
|
||||
export { callGateway } from "../../../gateway/call.js";
|
||||
export { dispatchGatewayMethodInProcess } from "../../../gateway/server-plugins.js";
|
||||
export { resolveQueueSettings } from "../../../auto-reply/reply/queue.js";
|
||||
export { resolveExternalBestEffortDeliveryTarget } from "../../../infra/outbound/best-effort-delivery.js";
|
||||
export { sendMessage } from "../../../infra/outbound/message.js";
|
||||
export { createBoundDeliveryRouter } from "../../../infra/outbound/bound-delivery-router.js";
|
||||
export { resolveConversationIdFromTargets } from "../../../infra/outbound/conversation-id.js";
|
||||
export { getGlobalHookRunner } from "../../../plugins/hook-runner-global.js";
|
||||
export {
|
||||
formatEmbeddedAgentQueueFailureSummary,
|
||||
isEmbeddedAgentRunActive,
|
||||
isEmbeddedRunAbandoned,
|
||||
queueEmbeddedAgentMessageWithOutcomeAsync,
|
||||
resolveActiveEmbeddedRunSessionId,
|
||||
} from "../../embedded-agent-runner/runs.js";
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
export * from "./subagent-announce-delivery.js";
|
||||
|
||||
type QueueMessageOptions =
|
||||
import("./embedded-agent-runner/runs.js").EmbeddedAgentQueueMessageOptions;
|
||||
import("../../embedded-agent-runner/runs.js").EmbeddedAgentQueueMessageOptions;
|
||||
type QueueMessageOutcome =
|
||||
import("./embedded-agent-runner/runs.js").EmbeddedAgentQueueMessageOutcome;
|
||||
import("../../embedded-agent-runner/runs.js").EmbeddedAgentQueueMessageOutcome;
|
||||
type DeliveryDeps = {
|
||||
callGateway: typeof import("./subagent-announce-delivery.runtime.js").callGateway;
|
||||
dispatchGatewayMethodInProcess: typeof import("./subagent-announce-delivery.runtime.js").dispatchGatewayMethodInProcess;
|
||||
+27
-24
@@ -1,24 +1,36 @@
|
||||
// Subagent announce delivery tests cover the last-mile routing used when child
|
||||
// runs report progress or completion back to the requester session.
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { SessionEntry } from "../config/sessions.js";
|
||||
import { OutboundDeliveryError } from "../infra/outbound/deliver-types.js";
|
||||
import type { SessionEntry } from "../../../config/sessions.js";
|
||||
import { OutboundDeliveryError } from "../../../infra/outbound/deliver-types.js";
|
||||
import {
|
||||
testing as sessionBindingServiceTesting,
|
||||
registerSessionBindingAdapter,
|
||||
} from "../infra/outbound/session-binding-service.js";
|
||||
import { normalizeLegacySessionEntryDelivery } from "../infra/state-migrations.legacy-session-store.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { createChannelTestPluginBase, createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||
} from "../../../infra/outbound/session-binding-service.js";
|
||||
import { normalizeLegacySessionEntryDelivery } from "../../../infra/state-migrations.legacy-session-store.js";
|
||||
import { setActivePluginRegistry } from "../../../plugins/runtime.js";
|
||||
import {
|
||||
createChannelTestPluginBase,
|
||||
createTestRegistry,
|
||||
} from "../../../test-utils/channel-plugins.js";
|
||||
import type {
|
||||
EmbeddedAgentQueueMessageOptions,
|
||||
EmbeddedAgentQueueMessageOutcome,
|
||||
} from "./embedded-agent-runner/runs.js";
|
||||
import type { AgentInternalEvent } from "./internal-events.js";
|
||||
} from "../../embedded-agent-runner/runs.js";
|
||||
import type { AgentInternalEvent } from "../../internal-events.js";
|
||||
import {
|
||||
INTERNAL_RUNTIME_CONTEXT_BEGIN,
|
||||
INTERNAL_RUNTIME_CONTEXT_END,
|
||||
} from "./internal-runtime-context.js";
|
||||
} from "../../internal-runtime-context.js";
|
||||
import {
|
||||
createTaskCompletionEvent,
|
||||
expectDeliveryPath,
|
||||
expectRecordFields,
|
||||
imageCompletionEvents,
|
||||
mockCallArg,
|
||||
musicCompletionEvents,
|
||||
taskCompletionEvents,
|
||||
} from "../../subagent-test-fixtures.test-helpers.js";
|
||||
import {
|
||||
callGateway as runtimeCallGateway,
|
||||
dispatchGatewayMethodInProcess as runtimeDispatchGatewayMethodInProcess,
|
||||
@@ -29,15 +41,6 @@ import {
|
||||
resolveAnnounceOrigin,
|
||||
resolveSubagentCompletionOrigin,
|
||||
} from "./subagent-announce-origin.js";
|
||||
import {
|
||||
createTaskCompletionEvent,
|
||||
expectDeliveryPath,
|
||||
expectRecordFields,
|
||||
imageCompletionEvents,
|
||||
mockCallArg,
|
||||
musicCompletionEvents,
|
||||
taskCompletionEvents,
|
||||
} from "./subagent-test-fixtures.test-helpers.js";
|
||||
|
||||
const sessionDeliveryQueueMocks = vi.hoisted(() => ({
|
||||
enqueueClaimedSessionDelivery: vi.fn((_payload: unknown, _leaseMs: number) => ({
|
||||
@@ -49,20 +52,20 @@ const sessionDeliveryQueueMocks = vi.hoisted(() => ({
|
||||
scheduleSessionDelivery: vi.fn(async () => true),
|
||||
}));
|
||||
|
||||
vi.mock("./subagent-completion-delivery.js", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("./subagent-completion-delivery.js")>()),
|
||||
vi.mock("../completion/subagent-completion-delivery.js", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("../completion/subagent-completion-delivery.js")>()),
|
||||
admitCorrelatedSubagentSessionDelivery: (params: { payload: Record<string, unknown> }) =>
|
||||
sessionDeliveryQueueMocks.enqueueClaimedSessionDelivery(params.payload, 125_000),
|
||||
}));
|
||||
|
||||
vi.mock("../infra/session-delivery-queue.js", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("../infra/session-delivery-queue.js")>()),
|
||||
vi.mock("../../../infra/session-delivery-queue.js", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("../../../infra/session-delivery-queue.js")>()),
|
||||
enqueueClaimedSessionDelivery: sessionDeliveryQueueMocks.enqueueClaimedSessionDelivery,
|
||||
releaseSessionDeliveryClaim: sessionDeliveryQueueMocks.releaseSessionDeliveryClaim,
|
||||
}));
|
||||
|
||||
vi.mock("../infra/session-delivery-queue-runtime.js", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("../infra/session-delivery-queue-runtime.js")>()),
|
||||
vi.mock("../../../infra/session-delivery-queue-runtime.js", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("../../../infra/session-delivery-queue-runtime.js")>()),
|
||||
scheduleSessionDelivery: sessionDeliveryQueueMocks.scheduleSessionDelivery,
|
||||
}));
|
||||
|
||||
+31
-28
@@ -6,34 +6,34 @@
|
||||
import { clampTimerTimeoutMs } from "@openclaw/normalization-core/number-coercion";
|
||||
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { normalizeUniqueTrimmedStringList } from "@openclaw/normalization-core/string-normalization";
|
||||
import { completionRequiresMessageToolDelivery } from "../auto-reply/reply/completion-delivery-policy.js";
|
||||
import { sanitizePendingFinalDeliveryText } from "../auto-reply/reply/pending-final-delivery.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { isFastTestRuntimeEnv } from "../infra/env.js";
|
||||
import { isOutboundDeliveryError } from "../infra/outbound/deliver-types.js";
|
||||
import { sourceDeliveryTargetsMatch } from "../infra/outbound/source-delivery-plan.js";
|
||||
import { scheduleSessionDelivery } from "../infra/session-delivery-queue-runtime.js";
|
||||
import { completionRequiresMessageToolDelivery } from "../../../auto-reply/reply/completion-delivery-policy.js";
|
||||
import { sanitizePendingFinalDeliveryText } from "../../../auto-reply/reply/pending-final-delivery.js";
|
||||
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
|
||||
import { isFastTestRuntimeEnv } from "../../../infra/env.js";
|
||||
import { isOutboundDeliveryError } from "../../../infra/outbound/deliver-types.js";
|
||||
import { sourceDeliveryTargetsMatch } from "../../../infra/outbound/source-delivery-plan.js";
|
||||
import { scheduleSessionDelivery } from "../../../infra/session-delivery-queue-runtime.js";
|
||||
import {
|
||||
enqueueClaimedSessionDelivery,
|
||||
releaseSessionDeliveryClaim,
|
||||
} from "../infra/session-delivery-queue.js";
|
||||
import { stringifyRouteThreadId } from "../plugin-sdk/channel-route.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
} from "../../../infra/session-delivery-queue.js";
|
||||
import { stringifyRouteThreadId } from "../../../plugin-sdk/channel-route.js";
|
||||
import { defaultRuntime } from "../../../runtime.js";
|
||||
import {
|
||||
isAgentMediatedCompletionSourceTool,
|
||||
shouldPreserveUserFacingSessionStateForInputProvenance,
|
||||
} from "../sessions/input-provenance.js";
|
||||
import { deriveSessionChatTypeFromKey } from "../sessions/session-chat-type-shared.js";
|
||||
import { isCronRunSessionKey, isCronSessionKey } from "../sessions/session-key-utils.js";
|
||||
import { isNonTerminalAgentRunStatus } from "../shared/agent-run-status.js";
|
||||
import { sessionDeliveryChannel } from "../utils/delivery-context.shared.js";
|
||||
} from "../../../sessions/input-provenance.js";
|
||||
import { deriveSessionChatTypeFromKey } from "../../../sessions/session-chat-type-shared.js";
|
||||
import { isCronRunSessionKey, isCronSessionKey } from "../../../sessions/session-key-utils.js";
|
||||
import { isNonTerminalAgentRunStatus } from "../../../shared/agent-run-status.js";
|
||||
import { sessionDeliveryChannel } from "../../../utils/delivery-context.shared.js";
|
||||
import {
|
||||
INTERNAL_MESSAGE_CHANNEL,
|
||||
isGatewayMessageChannel,
|
||||
normalizeMessageChannel,
|
||||
} from "../utils/message-channel.js";
|
||||
import { sanitizeAgentRunTerminalReplyText } from "./agent-run-terminal-reply.js";
|
||||
import { resolveDefaultAgentId } from "./agent-scope-config.js";
|
||||
} from "../../../utils/message-channel.js";
|
||||
import { sanitizeAgentRunTerminalReplyText } from "../../agent-run-terminal-reply.js";
|
||||
import { resolveDefaultAgentId } from "../../agent-scope-config.js";
|
||||
import {
|
||||
getAgentCommandDeliveryFailure,
|
||||
getGatewayAgentResult,
|
||||
@@ -43,20 +43,25 @@ import {
|
||||
hasPayloadOutcomeSendEvidence,
|
||||
hasUnaccountedMessagingToolAggregateEvidence,
|
||||
resolveExplicitFinalSourceReplyDeliveryEvidence,
|
||||
} from "./embedded-agent-runner/delivery-evidence.js";
|
||||
} from "../../embedded-agent-runner/delivery-evidence.js";
|
||||
import {
|
||||
hasIntentionalSilentAgentPayload,
|
||||
hasVisibleAgentPayload,
|
||||
} from "./embedded-agent-runner/message-visibility.js";
|
||||
import type { EmbeddedAgentQueueMessageOptions } from "./embedded-agent-runner/run-state.js";
|
||||
import type { EmbeddedAgentQueueMessageOutcome } from "./embedded-agent-runner/runs.js";
|
||||
import { isFailoverError } from "./failover-error.js";
|
||||
import { mediaUrlsFromGeneratedAttachments } from "./generated-attachments.js";
|
||||
} from "../../embedded-agent-runner/message-visibility.js";
|
||||
import type { EmbeddedAgentQueueMessageOptions } from "../../embedded-agent-runner/run-state.js";
|
||||
import type { EmbeddedAgentQueueMessageOutcome } from "../../embedded-agent-runner/runs.js";
|
||||
import { isFailoverError } from "../../failover-error.js";
|
||||
import { mediaUrlsFromGeneratedAttachments } from "../../generated-attachments.js";
|
||||
import {
|
||||
AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION,
|
||||
hasGeneratedMediaCompletionEvent,
|
||||
} from "./internal-event-contract.js";
|
||||
import { formatAgentInternalEventsForPrompt, type AgentInternalEvent } from "./internal-events.js";
|
||||
} from "../../internal-event-contract.js";
|
||||
import {
|
||||
formatAgentInternalEventsForPrompt,
|
||||
type AgentInternalEvent,
|
||||
} from "../../internal-events.js";
|
||||
import { admitCorrelatedSubagentSessionDelivery } from "../completion/subagent-completion-delivery.js";
|
||||
import { getSubagentDepthFromSessionStore } from "../spawn/subagent-depth.js";
|
||||
import {
|
||||
callGateway,
|
||||
dispatchGatewayMethodInProcess,
|
||||
@@ -84,8 +89,6 @@ import {
|
||||
resolveGeneratedMediaSessionDeliveryRoute,
|
||||
type DeliveryContext,
|
||||
} from "./subagent-announce-origin.js";
|
||||
import { admitCorrelatedSubagentSessionDelivery } from "./subagent-completion-delivery.js";
|
||||
import { getSubagentDepthFromSessionStore } from "./subagent-depth.js";
|
||||
import { resolveRequesterStoreKey } from "./subagent-requester-store-key.js";
|
||||
|
||||
const DEFAULT_SUBAGENT_ANNOUNCE_TIMEOUT_MS = 120_000;
|
||||
+5
-5
@@ -1,9 +1,10 @@
|
||||
// Descendant-settle wake replaces an ended nested orchestrator run while
|
||||
// preserving lifecycle ownership.
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { getAgentEventLifecycleGeneration } from "../infra/agent-events.js";
|
||||
import { INTERNAL_MESSAGE_CHANNEL } from "../utils/message-channel.js";
|
||||
import { buildAnnounceIdempotencyKey } from "./announce-idempotency.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../../../infra/agent-events.js";
|
||||
import { INTERNAL_MESSAGE_CHANNEL } from "../../../utils/message-channel.js";
|
||||
import { buildAnnounceIdempotencyKey } from "../../announce-idempotency.js";
|
||||
import { terminateAcceptedCollectorRun } from "../spawn/subagent-spawn-cleanup.js";
|
||||
import {
|
||||
loadSessionEntryByKey,
|
||||
runAnnounceDeliveryWithRetry,
|
||||
@@ -14,13 +15,12 @@ import type {
|
||||
dispatchGatewayMethodInProcess,
|
||||
getRuntimeConfig,
|
||||
} from "./subagent-announce.runtime.js";
|
||||
import { terminateAcceptedCollectorRun } from "./subagents/spawn/subagent-spawn-cleanup.js";
|
||||
|
||||
type DescendantWakeDeps = {
|
||||
callGateway: typeof callGateway;
|
||||
dispatchGatewayMethodInProcess: typeof dispatchGatewayMethodInProcess;
|
||||
getRuntimeConfig: typeof getRuntimeConfig;
|
||||
replaceSubagentRunAfterSteer: typeof import("./subagent-registry-runtime.js").replaceSubagentRunAfterSteer;
|
||||
replaceSubagentRunAfterSteer: typeof import("../registry/subagent-registry-runtime.js").replaceSubagentRunAfterSteer;
|
||||
};
|
||||
|
||||
type UsableSessionEntryGuard = (entry: unknown) => entry is Record<string, unknown>;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION } from "./internal-event-contract.js";
|
||||
import type { AgentInternalEvent } from "./internal-events.js";
|
||||
import { AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION } from "../../internal-event-contract.js";
|
||||
import type { AgentInternalEvent } from "../../internal-events.js";
|
||||
import {
|
||||
isSubagentAnnounceCompletionHandoff,
|
||||
isTrustedSubagentCompletionHandoffForRun,
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import type { InputProvenance } from "../sessions/input-provenance.js";
|
||||
import { AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION } from "./internal-event-contract.js";
|
||||
import type { AgentInternalEvent } from "./internal-events.js";
|
||||
import type { InputProvenance } from "../../../sessions/input-provenance.js";
|
||||
import { AGENT_INTERNAL_EVENT_TYPE_TASK_COMPLETION } from "../../internal-event-contract.js";
|
||||
import type { AgentInternalEvent } from "../../internal-events.js";
|
||||
|
||||
export type TrustedSubagentCompletionHandoff = {
|
||||
kind: "subagent-completion";
|
||||
+18
-15
@@ -7,40 +7,43 @@ import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "@openclaw/normalization-core/string-coerce";
|
||||
import { getLoadedChannelPluginForRead } from "../channels/plugins/registry-loaded.js";
|
||||
import type { ChannelId } from "../channels/plugins/types.public.js";
|
||||
import { routeFromConversationRef, routeToDeliveryFields } from "../channels/route-projection.js";
|
||||
import type { SessionEntry } from "../config/sessions/types.js";
|
||||
import { getLoadedChannelPluginForRead } from "../../../channels/plugins/registry-loaded.js";
|
||||
import type { ChannelId } from "../../../channels/plugins/types.public.js";
|
||||
import {
|
||||
routeFromConversationRef,
|
||||
routeToDeliveryFields,
|
||||
} from "../../../channels/route-projection.js";
|
||||
import type { SessionEntry } from "../../../config/sessions/types.js";
|
||||
import {
|
||||
stripTargetKindPrefix,
|
||||
stripTargetProviderPrefix,
|
||||
stripTargetTopicSuffix,
|
||||
} from "../infra/outbound/channel-target-prefix.js";
|
||||
import type { ConversationRef } from "../infra/outbound/session-binding-service.js";
|
||||
import type { SessionDeliveryRoute } from "../infra/session-delivery-queue.js";
|
||||
import { stringifyRouteThreadId } from "../plugin-sdk/channel-route.js";
|
||||
import { normalizeAccountId } from "../routing/session-key.js";
|
||||
import { deriveSessionChatTypeFromKey } from "../sessions/session-chat-type-shared.js";
|
||||
} from "../../../infra/outbound/channel-target-prefix.js";
|
||||
import type { ConversationRef } from "../../../infra/outbound/session-binding-service.js";
|
||||
import type { SessionDeliveryRoute } from "../../../infra/session-delivery-queue.js";
|
||||
import { stringifyRouteThreadId } from "../../../plugin-sdk/channel-route.js";
|
||||
import { normalizeAccountId } from "../../../routing/session-key.js";
|
||||
import { deriveSessionChatTypeFromKey } from "../../../sessions/session-chat-type-shared.js";
|
||||
import {
|
||||
deliveryContextFromSession,
|
||||
mergeDeliveryContext,
|
||||
normalizeDeliveryContext,
|
||||
} from "../utils/delivery-context.shared.js";
|
||||
import type { DeliveryContext } from "../utils/delivery-context.types.js";
|
||||
} from "../../../utils/delivery-context.shared.js";
|
||||
import type { DeliveryContext } from "../../../utils/delivery-context.types.js";
|
||||
import {
|
||||
INTERNAL_MESSAGE_CHANNEL,
|
||||
isDeliverableMessageChannel,
|
||||
isGatewayMessageChannel,
|
||||
isInternalMessageChannel,
|
||||
normalizeMessageChannel,
|
||||
} from "../utils/message-channel.js";
|
||||
} from "../../../utils/message-channel.js";
|
||||
import type { SpawnSubagentMode } from "../spawn/subagent-spawn.types.js";
|
||||
import {
|
||||
createBoundDeliveryRouter,
|
||||
getGlobalHookRunner,
|
||||
resolveConversationIdFromTargets,
|
||||
} from "./subagent-announce-delivery.runtime.js";
|
||||
import type { SpawnSubagentMode } from "./subagents/spawn/subagent-spawn.types.js";
|
||||
export type { DeliveryContext } from "../utils/delivery-context.types.js";
|
||||
export type { DeliveryContext } from "../../../utils/delivery-context.types.js";
|
||||
|
||||
function normalizeAnnounceRouteTarget(context?: DeliveryContext): string | undefined {
|
||||
const rawTo = normalizeOptionalString(context?.to);
|
||||
+1
-1
@@ -10,7 +10,7 @@ import {
|
||||
readSubagentOutput,
|
||||
} from "./subagent-announce-output.test-support.js";
|
||||
|
||||
type CallGateway = typeof import("../gateway/call.js").callGateway;
|
||||
type CallGateway = typeof import("../../../gateway/call.js").callGateway;
|
||||
type GetRuntimeConfig = typeof import("./subagent-announce.runtime.js").getRuntimeConfig;
|
||||
type ReadSessionEntry = typeof import("./subagent-announce.runtime.js").readSessionEntry;
|
||||
type ReadSessionMessagesAsync =
|
||||
+13
-10
@@ -5,13 +5,19 @@
|
||||
*/
|
||||
import { asFiniteNumber } from "@openclaw/normalization-core/number-coercion";
|
||||
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
|
||||
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
|
||||
import type { SessionTranscriptRuntimeTarget } from "../config/sessions/session-accessor.js";
|
||||
import { resolveFreshSessionTotalTokens } from "../config/sessions/types.js";
|
||||
import { isFastTestRuntimeEnv } from "../infra/env.js";
|
||||
import { formatDurationCompact } from "../infra/format-time/format-duration.js";
|
||||
import { buildAgentRunTerminalOutcomeFromWaitResult } from "./agent-run-terminal-outcome.js";
|
||||
import { wrapPromptDataBlock } from "./sanitize-for-prompt.js";
|
||||
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../../../auto-reply/tokens.js";
|
||||
import type { SessionTranscriptRuntimeTarget } from "../../../config/sessions/session-accessor.js";
|
||||
import { resolveFreshSessionTotalTokens } from "../../../config/sessions/types.js";
|
||||
import { isFastTestRuntimeEnv } from "../../../infra/env.js";
|
||||
import { formatDurationCompact } from "../../../infra/format-time/format-duration.js";
|
||||
import { buildAgentRunTerminalOutcomeFromWaitResult } from "../../agent-run-terminal-outcome.js";
|
||||
import { wrapPromptDataBlock } from "../../sanitize-for-prompt.js";
|
||||
import { extractAssistantText, sanitizeTextContent } from "../../tools/chat-history-text.js";
|
||||
import {
|
||||
isAnnounceSkip,
|
||||
selectDeliverableSessionsReply,
|
||||
} from "../../tools/sessions-send-tokens.js";
|
||||
import { compareSubagentRunGeneration } from "../registry/subagent-run-generation.js";
|
||||
import {
|
||||
captureSubagentCompletionReplyUsing,
|
||||
readLatestSubagentOutputWithRetryUsing,
|
||||
@@ -24,10 +30,7 @@ import {
|
||||
resolveAgentIdFromSessionKey,
|
||||
resolveStorePath,
|
||||
} from "./subagent-announce.runtime.js";
|
||||
import { compareSubagentRunGeneration } from "./subagent-run-generation.js";
|
||||
import { assistantCallsSessionsYield, isSessionsYieldToolResult } from "./subagent-yield-output.js";
|
||||
import { extractAssistantText, sanitizeTextContent } from "./tools/chat-history-text.js";
|
||||
import { isAnnounceSkip, selectDeliverableSessionsReply } from "./tools/sessions-send-tokens.js";
|
||||
|
||||
const FAST_TEST_RETRY_INTERVAL_MS = 8;
|
||||
const MAX_CHILD_COMPLETION_RESULT_CHARS = 512;
|
||||
+20
-17
@@ -1,31 +1,34 @@
|
||||
// Subagent announce format e2e tests exercise the full announce flow with
|
||||
// channel fixtures, session stores, hooks, and gateway calls wired together.
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
|
||||
import { SILENT_REPLY_TOKEN } from "../../../auto-reply/tokens.js";
|
||||
import {
|
||||
clearRuntimeConfigSnapshot,
|
||||
setRuntimeConfigSnapshot,
|
||||
type OpenClawConfig,
|
||||
} from "../config/config.js";
|
||||
import * as configSessions from "../config/sessions.js";
|
||||
import type { SessionEntry } from "../config/sessions/types.js";
|
||||
import * as gatewayCall from "../gateway/call.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../infra/agent-events.js";
|
||||
} from "../../../config/config.js";
|
||||
import * as configSessions from "../../../config/sessions.js";
|
||||
import type { SessionEntry } from "../../../config/sessions/types.js";
|
||||
import * as gatewayCall from "../../../gateway/call.js";
|
||||
import { getAgentEventLifecycleGeneration } from "../../../infra/agent-events.js";
|
||||
import {
|
||||
testing as sessionBindingServiceTesting,
|
||||
registerSessionBindingAdapter,
|
||||
} from "../infra/outbound/session-binding-service.js";
|
||||
import { normalizeLegacySessionEntryDelivery } from "../infra/state-migrations.legacy-session-store.js";
|
||||
import * as hookRunnerGlobal from "../plugins/hook-runner-global.js";
|
||||
import type { HookRunner } from "../plugins/hooks.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { createChannelTestPluginBase, createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||
} from "../../../infra/outbound/session-binding-service.js";
|
||||
import { normalizeLegacySessionEntryDelivery } from "../../../infra/state-migrations.legacy-session-store.js";
|
||||
import * as hookRunnerGlobal from "../../../plugins/hook-runner-global.js";
|
||||
import type { HookRunner } from "../../../plugins/hooks.js";
|
||||
import { setActivePluginRegistry } from "../../../plugins/runtime.js";
|
||||
import {
|
||||
createChannelTestPluginBase,
|
||||
createTestRegistry,
|
||||
} from "../../../test-utils/channel-plugins.js";
|
||||
import {
|
||||
buildAnnounceIdFromChildRun,
|
||||
buildAnnounceIdempotencyKey,
|
||||
} from "./announce-idempotency.js";
|
||||
import * as embeddedRuns from "./embedded-agent-runner/runs.js";
|
||||
import { FailoverError } from "./failover-error.js";
|
||||
} from "../../announce-idempotency.js";
|
||||
import * as embeddedRuns from "../../embedded-agent-runner/runs.js";
|
||||
import { FailoverError } from "../../failover-error.js";
|
||||
import { testing as subagentAnnounceDeliveryTesting } from "./subagent-announce-delivery.test-support.js";
|
||||
import { runSubagentAnnounceDispatch } from "./subagent-announce-dispatch.js";
|
||||
import { testing as subagentAnnounceOutputTesting } from "./subagent-announce-output.test-support.js";
|
||||
@@ -332,8 +335,8 @@ function loadSessionStoreFixture(): Record<string, SessionEntry> {
|
||||
}) as unknown as Record<string, SessionEntry>;
|
||||
}
|
||||
|
||||
vi.mock("./subagent-registry.js", () => subagentRegistryMock);
|
||||
vi.mock("./subagent-registry-runtime.js", () => subagentRegistryMock);
|
||||
vi.mock("../registry/subagent-registry.js", () => subagentRegistryMock);
|
||||
vi.mock("../registry/subagent-registry-runtime.js", () => subagentRegistryMock);
|
||||
|
||||
describe("subagent announce formatting", () => {
|
||||
let previousFastTestEnv: string | undefined;
|
||||
+17
-14
@@ -4,25 +4,28 @@ import { randomBytes, randomUUID } from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { clearRuntimeConfigSnapshot, type OpenClawConfig } from "../config/config.js";
|
||||
import { callGateway as realCallGateway } from "../gateway/call.js";
|
||||
import { GatewayClient } from "../gateway/client.js";
|
||||
import { dispatchGatewayMethodInProcess as realDispatchGatewayMethodInProcess } from "../gateway/server-plugins.js";
|
||||
import { startGatewayServer, type GatewayServer } from "../gateway/server.js";
|
||||
import { extractPayloadText } from "../gateway/test-helpers.agent-results.js";
|
||||
import { onAgentEvent, type AgentEventPayload } from "../infra/agent-events.js";
|
||||
import { isTruthyEnvValue } from "../infra/env.js";
|
||||
import { clearCurrentPluginMetadataSnapshot } from "../plugins/current-plugin-metadata-state.js";
|
||||
import { clearRuntimeConfigSnapshot, type OpenClawConfig } from "../../../config/config.js";
|
||||
import { callGateway as realCallGateway } from "../../../gateway/call.js";
|
||||
import { GatewayClient } from "../../../gateway/client.js";
|
||||
import { dispatchGatewayMethodInProcess as realDispatchGatewayMethodInProcess } from "../../../gateway/server-plugins.js";
|
||||
import { startGatewayServer, type GatewayServer } from "../../../gateway/server.js";
|
||||
import { extractPayloadText } from "../../../gateway/test-helpers.agent-results.js";
|
||||
import { onAgentEvent, type AgentEventPayload } from "../../../infra/agent-events.js";
|
||||
import { isTruthyEnvValue } from "../../../infra/env.js";
|
||||
import { clearCurrentPluginMetadataSnapshot } from "../../../plugins/current-plugin-metadata-state.js";
|
||||
import {
|
||||
createOpenClawTestState,
|
||||
type OpenClawTestState,
|
||||
} from "../test-utils/openclaw-test-state.js";
|
||||
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
|
||||
import { isLiveTestEnabled, readLiveTestConfig } from "./live-test-helpers.js";
|
||||
} from "../../../test-utils/openclaw-test-state.js";
|
||||
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../../../utils/message-channel.js";
|
||||
import { isLiveTestEnabled, readLiveTestConfig } from "../../live-test-helpers.js";
|
||||
import {
|
||||
resolveSubagentController,
|
||||
steerControlledSubagentRun,
|
||||
} from "../registry/subagent-control.js";
|
||||
import { listSubagentRunsForRequester } from "../registry/subagent-registry.test-helpers.js";
|
||||
import { testing as subagentAnnounceDeliveryTesting } from "./subagent-announce-delivery.test-support.js";
|
||||
import { testing as subagentAnnounceTesting } from "./subagent-announce.js";
|
||||
import { resolveSubagentController, steerControlledSubagentRun } from "./subagent-control.js";
|
||||
import { listSubagentRunsForRequester } from "./subagent-registry.test-helpers.js";
|
||||
|
||||
const LIVE = isLiveTestEnabled() && isTruthyEnvValue(process.env.OPENCLAW_LIVE_SUBAGENT_E2E);
|
||||
const describeLive = LIVE ? describe : describe.skip;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user