Skip to content

Commit af8e196

Browse files
authored
refactor: split main-action.ts into validate-options and build-config modules (#3229)
* Initial plan * refactor: split main-action.ts into focused modules * test: add validate-options unit tests --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 93343df commit af8e196

5 files changed

Lines changed: 1260 additions & 446 deletions

File tree

src/commands/build-config.ts

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { WrapperConfig, LogLevel, UpstreamProxyConfig } from '../types';
2+
import { resolveCopilotApiKey } from '../copilot-api-resolver';
3+
4+
/**
5+
* Inputs required to assemble a {@link WrapperConfig}.
6+
*
7+
* All fields must already be parsed and validated by the caller.
8+
*/
9+
export interface BuildConfigInputs {
10+
options: Record<string, unknown>;
11+
agentCommand: string;
12+
logLevel: LogLevel;
13+
allowedDomains: string[];
14+
blockedDomains: string[];
15+
localhostDetected: boolean;
16+
additionalEnv: Record<string, string>;
17+
volumeMounts: string[] | undefined;
18+
upstreamProxy: UpstreamProxyConfig | undefined;
19+
dnsServers: string[];
20+
dnsOverHttps: string | undefined;
21+
allowedUrls: string[] | undefined;
22+
memoryLimit: string | undefined;
23+
agentImage: string | undefined;
24+
modelAliases: Record<string, string[]> | undefined;
25+
maxEffectiveTokens: number | undefined;
26+
effectiveTokenModelMultipliers: Record<string, number> | undefined;
27+
maxRuns: number | undefined;
28+
resolvedCopilotApiTarget: string | undefined;
29+
resolvedCopilotApiBasePath: string | undefined;
30+
dockerHostPathPrefix: string | undefined;
31+
}
32+
33+
/**
34+
* Assembles a {@link WrapperConfig} from pre-parsed and pre-validated inputs.
35+
*
36+
* This function performs no validation — callers must validate before calling.
37+
* API keys are resolved from the process environment here to keep credential
38+
* access centralised in one place.
39+
*/
40+
export function buildConfig(inputs: BuildConfigInputs): WrapperConfig {
41+
const {
42+
options,
43+
agentCommand,
44+
logLevel,
45+
allowedDomains,
46+
blockedDomains,
47+
localhostDetected,
48+
additionalEnv,
49+
volumeMounts,
50+
upstreamProxy,
51+
dnsServers,
52+
dnsOverHttps,
53+
allowedUrls,
54+
memoryLimit,
55+
agentImage,
56+
modelAliases,
57+
maxEffectiveTokens,
58+
effectiveTokenModelMultipliers,
59+
maxRuns,
60+
resolvedCopilotApiTarget,
61+
resolvedCopilotApiBasePath,
62+
dockerHostPathPrefix,
63+
} = inputs;
64+
65+
return {
66+
allowedDomains,
67+
blockedDomains: blockedDomains.length > 0 ? blockedDomains : undefined,
68+
agentCommand,
69+
logLevel,
70+
keepContainers: options.keepContainers as boolean,
71+
tty: (options.tty as boolean) || false,
72+
workDir: options.workDir as string,
73+
buildLocal: options.buildLocal as boolean,
74+
skipPull: options.skipPull as boolean,
75+
agentImage,
76+
imageRegistry: options.imageRegistry as string,
77+
imageTag: options.imageTag as string,
78+
additionalEnv: Object.keys(additionalEnv).length > 0 ? additionalEnv : undefined,
79+
envAll: options.envAll as boolean,
80+
excludeEnv:
81+
options.excludeEnv && (options.excludeEnv as string[]).length > 0
82+
? (options.excludeEnv as string[])
83+
: undefined,
84+
envFile: options.envFile as string | undefined,
85+
volumeMounts,
86+
containerWorkDir: options.containerWorkdir as string | undefined,
87+
dnsServers,
88+
dnsOverHttps,
89+
memoryLimit,
90+
proxyLogsDir: options.proxyLogsDir as string | undefined,
91+
auditDir: (options.auditDir as string | undefined) || process.env.AWF_AUDIT_DIR,
92+
sessionStateDir:
93+
(options.sessionStateDir as string | undefined) || process.env.AWF_SESSION_STATE_DIR,
94+
enableHostAccess: options.enableHostAccess as boolean,
95+
localhostDetected,
96+
allowHostPorts: options.allowHostPorts as string | undefined,
97+
allowHostServicePorts: options.allowHostServicePorts as string | undefined,
98+
sslBump: options.sslBump as boolean,
99+
enableDind: options.enableDind as boolean,
100+
enableDlp: options.enableDlp as boolean,
101+
allowedUrls,
102+
enableApiProxy: options.enableApiProxy as boolean,
103+
enableOpenCode: options.enableOpencode as boolean,
104+
anthropicAutoCache: options.anthropicAutoCache as boolean,
105+
anthropicCacheTailTtl: options.anthropicCacheTailTtl as '5m' | '1h' | undefined,
106+
modelAliases,
107+
maxEffectiveTokens,
108+
effectiveTokenModelMultipliers,
109+
maxRuns,
110+
enableTokenSteering: options.enableTokenSteering as boolean,
111+
openaiApiKey: process.env.OPENAI_API_KEY,
112+
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
113+
copilotGithubToken: process.env.COPILOT_GITHUB_TOKEN,
114+
copilotApiKey: resolveCopilotApiKey(process.env),
115+
geminiApiKey: process.env.GEMINI_API_KEY,
116+
copilotApiTarget: resolvedCopilotApiTarget,
117+
copilotApiBasePath: resolvedCopilotApiBasePath,
118+
openaiApiTarget:
119+
(options.openaiApiTarget as string | undefined) || process.env.OPENAI_API_TARGET,
120+
openaiApiBasePath:
121+
(options.openaiApiBasePath as string | undefined) || process.env.OPENAI_API_BASE_PATH,
122+
anthropicApiTarget:
123+
(options.anthropicApiTarget as string | undefined) || process.env.ANTHROPIC_API_TARGET,
124+
anthropicApiBasePath:
125+
(options.anthropicApiBasePath as string | undefined) || process.env.ANTHROPIC_API_BASE_PATH,
126+
geminiApiTarget:
127+
(options.geminiApiTarget as string | undefined) || process.env.GEMINI_API_TARGET,
128+
geminiApiBasePath:
129+
(options.geminiApiBasePath as string | undefined) || process.env.GEMINI_API_BASE_PATH,
130+
difcProxyHost: options.difcProxyHost as string | undefined,
131+
difcProxyCaCert: options.difcProxyCaCert as string | undefined,
132+
githubToken: process.env.GITHUB_TOKEN || process.env.GH_TOKEN,
133+
diagnosticLogs: (options.diagnosticLogs as boolean) || false,
134+
awfDockerHost: options.dockerHost as string | undefined,
135+
upstreamProxy,
136+
dockerHostPathPrefix,
137+
};
138+
}

0 commit comments

Comments
 (0)