11import fs from "node:fs" ;
22import path from "node:path" ;
33import { resolveAgentModelFallbackValues } from "../config/model-input.js" ;
4- import { resolveStateDir } from "../config/paths.js" ;
54import type { AgentDefaultsConfig } from "../config/types.agent-defaults.js" ;
65import type { OpenClawConfig } from "../config/types.js" ;
7- import { createSubsystemLogger } from "../logging/subsystem.js" ;
86import {
9- DEFAULT_AGENT_ID ,
107 normalizeAgentId ,
118 parseAgentSessionKey ,
129 resolveAgentIdFromSessionKey ,
@@ -15,19 +12,28 @@ import {
1512 lowercasePreservingWhitespace ,
1613 normalizeLowercaseStringOrEmpty ,
1714 normalizeOptionalString ,
18- readStringValue ,
1915 resolvePrimaryStringValue ,
2016} from "../shared/string-coerce.js" ;
2117import { resolveUserPath } from "../utils.js" ;
18+ import {
19+ listAgentEntries ,
20+ listAgentIds ,
21+ resolveAgentConfig ,
22+ resolveAgentDir ,
23+ resolveAgentWorkspaceDir ,
24+ resolveDefaultAgentId ,
25+ type ResolvedAgentConfig ,
26+ } from "./agent-scope-config.js" ;
2227import { resolveEffectiveAgentSkillFilter } from "./skills/agent-filter.js" ;
23- import { resolveDefaultAgentWorkspaceDir } from "./workspace.js" ;
24-
25- let log : ReturnType < typeof createSubsystemLogger > | null = null ;
26-
27- function getLog ( ) : ReturnType < typeof createSubsystemLogger > {
28- log ??= createSubsystemLogger ( "agent-scope" ) ;
29- return log ;
30- }
28+ export {
29+ listAgentEntries ,
30+ listAgentIds ,
31+ resolveAgentConfig ,
32+ resolveAgentDir ,
33+ resolveAgentWorkspaceDir ,
34+ resolveDefaultAgentId ,
35+ type ResolvedAgentConfig ,
36+ } from "./agent-scope-config.js" ;
3137
3238/** Strip null bytes from paths to prevent ENOTDIR errors. */
3339function stripNullBytes ( s : string ) : string {
@@ -37,72 +43,6 @@ function stripNullBytes(s: string): string {
3743
3844export { resolveAgentIdFromSessionKey } ;
3945
40- type AgentEntry = NonNullable < NonNullable < OpenClawConfig [ "agents" ] > [ "list" ] > [ number ] ;
41-
42- type ResolvedAgentConfig = {
43- name ?: string ;
44- workspace ?: string ;
45- agentDir ?: string ;
46- systemPromptOverride ?: AgentEntry [ "systemPromptOverride" ] ;
47- model ?: AgentEntry [ "model" ] ;
48- thinkingDefault ?: AgentEntry [ "thinkingDefault" ] ;
49- verboseDefault ?: AgentDefaultsConfig [ "verboseDefault" ] ;
50- reasoningDefault ?: AgentEntry [ "reasoningDefault" ] ;
51- fastModeDefault ?: AgentEntry [ "fastModeDefault" ] ;
52- skills ?: AgentEntry [ "skills" ] ;
53- memorySearch ?: AgentEntry [ "memorySearch" ] ;
54- humanDelay ?: AgentEntry [ "humanDelay" ] ;
55- heartbeat ?: AgentEntry [ "heartbeat" ] ;
56- identity ?: AgentEntry [ "identity" ] ;
57- groupChat ?: AgentEntry [ "groupChat" ] ;
58- subagents ?: AgentEntry [ "subagents" ] ;
59- embeddedPi ?: AgentEntry [ "embeddedPi" ] ;
60- sandbox ?: AgentEntry [ "sandbox" ] ;
61- tools ?: AgentEntry [ "tools" ] ;
62- } ;
63-
64- let defaultAgentWarned = false ;
65-
66- export function listAgentEntries ( cfg : OpenClawConfig ) : AgentEntry [ ] {
67- const list = cfg . agents ?. list ;
68- if ( ! Array . isArray ( list ) ) {
69- return [ ] ;
70- }
71- return list . filter ( ( entry ) : entry is AgentEntry => entry !== null && typeof entry === "object" ) ;
72- }
73-
74- export function listAgentIds ( cfg : OpenClawConfig ) : string [ ] {
75- const agents = listAgentEntries ( cfg ) ;
76- if ( agents . length === 0 ) {
77- return [ DEFAULT_AGENT_ID ] ;
78- }
79- const seen = new Set < string > ( ) ;
80- const ids : string [ ] = [ ] ;
81- for ( const entry of agents ) {
82- const id = normalizeAgentId ( entry ?. id ) ;
83- if ( seen . has ( id ) ) {
84- continue ;
85- }
86- seen . add ( id ) ;
87- ids . push ( id ) ;
88- }
89- return ids . length > 0 ? ids : [ DEFAULT_AGENT_ID ] ;
90- }
91-
92- export function resolveDefaultAgentId ( cfg : OpenClawConfig ) : string {
93- const agents = listAgentEntries ( cfg ) ;
94- if ( agents . length === 0 ) {
95- return DEFAULT_AGENT_ID ;
96- }
97- const defaults = agents . filter ( ( agent ) => agent ?. default ) ;
98- if ( defaults . length > 1 && ! defaultAgentWarned ) {
99- defaultAgentWarned = true ;
100- getLog ( ) . warn ( "Multiple agents marked default=true; using the first entry as default." ) ;
101- }
102- const chosen = ( defaults [ 0 ] ?? agents [ 0 ] ) ?. id ?. trim ( ) ;
103- return normalizeAgentId ( chosen || DEFAULT_AGENT_ID ) ;
104- }
105-
10646export function resolveSessionAgentIds ( params : {
10747 sessionKey ?: string ;
10848 config ?: OpenClawConfig ;
@@ -129,48 +69,6 @@ export function resolveSessionAgentId(params: {
12969 return resolveSessionAgentIds ( params ) . sessionAgentId ;
13070}
13171
132- function resolveAgentEntry ( cfg : OpenClawConfig , agentId : string ) : AgentEntry | undefined {
133- const id = normalizeAgentId ( agentId ) ;
134- return listAgentEntries ( cfg ) . find ( ( entry ) => normalizeAgentId ( entry . id ) === id ) ;
135- }
136-
137- export function resolveAgentConfig (
138- cfg : OpenClawConfig ,
139- agentId : string ,
140- ) : ResolvedAgentConfig | undefined {
141- const id = normalizeAgentId ( agentId ) ;
142- const entry = resolveAgentEntry ( cfg , id ) ;
143- if ( ! entry ) {
144- return undefined ;
145- }
146- const agentDefaults = cfg . agents ?. defaults ;
147- return {
148- name : readStringValue ( entry . name ) ,
149- workspace : readStringValue ( entry . workspace ) ,
150- agentDir : readStringValue ( entry . agentDir ) ,
151- systemPromptOverride : readStringValue ( entry . systemPromptOverride ) ,
152- model :
153- typeof entry . model === "string" || ( entry . model && typeof entry . model === "object" )
154- ? entry . model
155- : undefined ,
156- thinkingDefault : entry . thinkingDefault ,
157- verboseDefault : entry . verboseDefault ?? agentDefaults ?. verboseDefault ,
158- reasoningDefault : entry . reasoningDefault ,
159- fastModeDefault : entry . fastModeDefault ,
160- skills : Array . isArray ( entry . skills ) ? entry . skills : undefined ,
161- memorySearch : entry . memorySearch ,
162- humanDelay : entry . humanDelay ,
163- heartbeat : entry . heartbeat ,
164- identity : entry . identity ,
165- groupChat : entry . groupChat ,
166- subagents : typeof entry . subagents === "object" && entry . subagents ? entry . subagents : undefined ,
167- embeddedPi :
168- typeof entry . embeddedPi === "object" && entry . embeddedPi ? entry . embeddedPi : undefined ,
169- sandbox : entry . sandbox ,
170- tools : entry . tools ,
171- } ;
172- }
173-
17472export function resolveAgentExecutionContract (
17573 cfg : OpenClawConfig | undefined ,
17674 agentId ?: string | null ,
@@ -276,29 +174,6 @@ export function resolveEffectiveModelFallbacks(params: {
276174 return agentFallbacksOverride ?? defaultFallbacks ;
277175}
278176
279- export function resolveAgentWorkspaceDir ( cfg : OpenClawConfig , agentId : string ) {
280- const id = normalizeAgentId ( agentId ) ;
281- const configured = resolveAgentConfig ( cfg , id ) ?. workspace ?. trim ( ) ;
282- if ( configured ) {
283- return stripNullBytes ( resolveUserPath ( configured ) ) ;
284- }
285- const defaultAgentId = resolveDefaultAgentId ( cfg ) ;
286- const fallback = cfg . agents ?. defaults ?. workspace ?. trim ( ) ;
287- if ( id === defaultAgentId ) {
288- if ( fallback ) {
289- return stripNullBytes ( resolveUserPath ( fallback ) ) ;
290- }
291- return stripNullBytes ( resolveDefaultAgentWorkspaceDir ( process . env ) ) ;
292- }
293- // Non-default agents: use the configured default workspace as a base so that
294- // agents.defaults.workspace is respected for all agents, not just the default.
295- if ( fallback ) {
296- return stripNullBytes ( path . join ( resolveUserPath ( fallback ) , id ) ) ;
297- }
298- const stateDir = resolveStateDir ( process . env ) ;
299- return stripNullBytes ( path . join ( stateDir , `workspace-${ id } ` ) ) ;
300- }
301-
302177function normalizePathForComparison ( input : string ) : string {
303178 const resolved = path . resolve ( stripNullBytes ( resolveUserPath ( input ) ) ) ;
304179 let normalized = resolved ;
@@ -354,17 +229,3 @@ export function resolveAgentIdByWorkspacePath(
354229) : string | undefined {
355230 return resolveAgentIdsByWorkspacePath ( cfg , workspacePath ) [ 0 ] ;
356231}
357-
358- export function resolveAgentDir (
359- cfg : OpenClawConfig ,
360- agentId : string ,
361- env : NodeJS . ProcessEnv = process . env ,
362- ) {
363- const id = normalizeAgentId ( agentId ) ;
364- const configured = resolveAgentConfig ( cfg , id ) ?. agentDir ?. trim ( ) ;
365- if ( configured ) {
366- return resolveUserPath ( configured , env ) ;
367- }
368- const root = resolveStateDir ( env ) ;
369- return path . join ( root , "agents" , id , "agent" ) ;
370- }
0 commit comments