fix(config): materialize subagent archive default (#81998) · openclaw/openclaw@82ab8a8
giodl73-repo
·
2026-05-17
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | import fsSync, { promises as fs } from "node:fs"; |
2 | 2 | import path from "node:path"; |
| 3 | +import { DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES } from "../config/agent-limits.js"; |
3 | 4 | import { getRuntimeConfig } from "../config/config.js"; |
4 | 5 | import { |
5 | 6 | loadSessionStore, |
@@ -345,7 +346,9 @@ export function reconcileOrphanedRestoredRuns(params: {
|
345 | 346 | |
346 | 347 | export function resolveArchiveAfterMs(cfg?: OpenClawConfig) { |
347 | 348 | const config = cfg ?? getRuntimeConfig(); |
348 | | -const minutes = config.agents?.defaults?.subagents?.archiveAfterMinutes ?? 60; |
| 349 | +const minutes = |
| 350 | +config.agents?.defaults?.subagents?.archiveAfterMinutes ?? |
| 351 | +DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES; |
349 | 352 | if (!Number.isFinite(minutes) || minutes < 0) { |
350 | 353 | return undefined; |
351 | 354 | } |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -950,6 +950,26 @@ describe("config cli", () => {
|
950 | 950 | |
951 | 951 | expect(mockLog).toHaveBeenCalledWith("__OPENCLAW_REDACTED__"); |
952 | 952 | }); |
| 953 | + |
| 954 | +it("prints materialized subagent archive default", async () => { |
| 955 | +const resolved: OpenClawConfig = {}; |
| 956 | +const config: OpenClawConfig = { |
| 957 | +agents: { |
| 958 | +defaults: { |
| 959 | +maxConcurrent: 4, |
| 960 | +subagents: { |
| 961 | +maxConcurrent: 8, |
| 962 | +archiveAfterMinutes: 60, |
| 963 | +}, |
| 964 | +}, |
| 965 | +}, |
| 966 | +}; |
| 967 | +setSnapshot(resolved, config); |
| 968 | + |
| 969 | +await runConfigCommand(["config", "get", "agents.defaults.subagents.archiveAfterMinutes"]); |
| 970 | + |
| 971 | +expect(mockLog).toHaveBeenCalledWith("60"); |
| 972 | +}); |
953 | 973 | }); |
954 | 974 | |
955 | 975 | describe("config validate", () => { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -3,6 +3,7 @@ import type { OpenClawConfig } from "./types.js";
|
3 | 3 | export const DEFAULT_AGENT_MAX_CONCURRENT = 4; |
4 | 4 | export const DEFAULT_SUBAGENT_MAX_CONCURRENT = 8; |
5 | 5 | export const DEFAULT_SUBAGENT_MAX_CHILDREN_PER_AGENT = 5; |
| 6 | +export const DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES = 60; |
6 | 7 | // Keep depth-1 subagents as leaves unless config explicitly opts into nesting. |
7 | 8 | export const DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH = 1; |
8 | 9 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | import { describe, expect, it } from "vitest"; |
2 | 2 | import { |
3 | 3 | DEFAULT_AGENT_MAX_CONCURRENT, |
| 4 | +DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES, |
4 | 5 | DEFAULT_SUBAGENT_MAX_CONCURRENT, |
5 | 6 | resolveAgentMaxConcurrent, |
6 | 7 | resolveSubagentMaxConcurrent, |
@@ -48,5 +49,8 @@ describe("agent concurrency defaults", () => {
|
48 | 49 | |
49 | 50 | expect(cfg.agents?.defaults?.maxConcurrent).toBe(DEFAULT_AGENT_MAX_CONCURRENT); |
50 | 51 | expect(cfg.agents?.defaults?.subagents?.maxConcurrent).toBe(DEFAULT_SUBAGENT_MAX_CONCURRENT); |
| 52 | +expect(cfg.agents?.defaults?.subagents?.archiveAfterMinutes).toBe( |
| 53 | +DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES, |
| 54 | +); |
51 | 55 | }); |
52 | 56 | }); |
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; |
2 | | -import { DEFAULT_AGENT_MAX_CONCURRENT, DEFAULT_SUBAGENT_MAX_CONCURRENT } from "./agent-limits.js"; |
| 2 | +import { |
| 3 | +DEFAULT_AGENT_MAX_CONCURRENT, |
| 4 | +DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES, |
| 5 | +DEFAULT_SUBAGENT_MAX_CONCURRENT, |
| 6 | +} from "./agent-limits.js"; |
3 | 7 | import { |
4 | 8 | applyAgentDefaults, |
5 | 9 | applyContextPruningDefaults, |
@@ -112,5 +116,17 @@ describe("config defaults", () => {
|
112 | 116 | |
113 | 117 | expect(next.agents?.defaults?.maxConcurrent).toBe(DEFAULT_AGENT_MAX_CONCURRENT); |
114 | 118 | expect(next.agents?.defaults?.subagents?.maxConcurrent).toBe(DEFAULT_SUBAGENT_MAX_CONCURRENT); |
| 119 | +expect(next.agents?.defaults?.subagents?.archiveAfterMinutes).toBe( |
| 120 | +DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES, |
| 121 | +); |
| 122 | +}); |
| 123 | + |
| 124 | +it("preserves explicit subagent archive default", () => { |
| 125 | +const next = applyAgentDefaults({ |
| 126 | +agents: { defaults: { subagents: { archiveAfterMinutes: 0 } } }, |
| 127 | +} as never); |
| 128 | + |
| 129 | +expect(next.agents?.defaults?.subagents?.archiveAfterMinutes).toBe(0); |
| 130 | +expect(next.agents?.defaults?.subagents?.maxConcurrent).toBe(DEFAULT_SUBAGENT_MAX_CONCURRENT); |
115 | 131 | }); |
116 | 132 | }); |
| Original file line number | Diff line number | Diff line change |
|---|
@@ -2,7 +2,11 @@ import { DEFAULT_CONTEXT_TOKENS } from "../agents/defaults.js";
|
2 | 2 | import { normalizeConfiguredProviderCatalogModelId } from "../agents/model-ref-shared.js"; |
3 | 3 | import { normalizeProviderId } from "../agents/provider-id.js"; |
4 | 4 | import type { PluginManifestRegistry } from "../plugins/manifest-registry.js"; |
5 | | -import { DEFAULT_AGENT_MAX_CONCURRENT, DEFAULT_SUBAGENT_MAX_CONCURRENT } from "./agent-limits.js"; |
| 5 | +import { |
| 6 | +DEFAULT_AGENT_MAX_CONCURRENT, |
| 7 | +DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES, |
| 8 | +DEFAULT_SUBAGENT_MAX_CONCURRENT, |
| 9 | +} from "./agent-limits.js"; |
6 | 10 | import { normalizeAgentModelMapForConfig, normalizeAgentModelRefForConfig } from "./model-input.js"; |
7 | 11 | import { |
8 | 12 | applyProviderConfigDefaultsForConfig, |
@@ -394,7 +398,10 @@ export function applyAgentDefaults(cfg: OpenClawConfig): OpenClawConfig {
|
394 | 398 | const hasSubMax = |
395 | 399 | typeof defaults?.subagents?.maxConcurrent === "number" && |
396 | 400 | Number.isFinite(defaults.subagents.maxConcurrent); |
397 | | -if (hasMax && hasSubMax) { |
| 401 | +const hasSubArchive = |
| 402 | +typeof defaults?.subagents?.archiveAfterMinutes === "number" && |
| 403 | +Number.isFinite(defaults.subagents.archiveAfterMinutes); |
| 404 | +if (hasMax && hasSubMax && hasSubArchive) { |
398 | 405 | return cfg; |
399 | 406 | } |
400 | 407 | |
@@ -410,6 +417,10 @@ export function applyAgentDefaults(cfg: OpenClawConfig): OpenClawConfig {
|
410 | 417 | nextSubagents.maxConcurrent = DEFAULT_SUBAGENT_MAX_CONCURRENT; |
411 | 418 | mutated = true; |
412 | 419 | } |
| 420 | +if (!hasSubArchive) { |
| 421 | +nextSubagents.archiveAfterMinutes = DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES; |
| 422 | +mutated = true; |
| 423 | +} |
413 | 424 | |
414 | 425 | if (!mutated) { |
415 | 426 | return cfg; |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。