Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/awf-config-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ the corresponding CLI flag.
- `container.tty` → `--tty`
- `container.dockerHost` → `--docker-host`
- `container.dockerHostPathPrefix` → `--docker-host-path-prefix`
- `container.runnerToolCachePath` → *(config-only; checked first for optional read-only runner tool cache mount, before `RUNNER_TOOL_CACHE` and `/home/runner/work/_tool` auto-detection)*
- `environment.envFile` → `--env-file`
- `environment.envAll` → `--env-all`
- `environment.excludeEnv[]` → `--exclude-env` *(repeatable)*
Expand Down
18 changes: 11 additions & 7 deletions docs/awf-config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable the API proxy sidecar container. When enabled, source credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, COPILOT_GITHUB_TOKEN, COPILOT_PROVIDER_API_KEY, GEMINI_API_KEY) are held exclusively in the sidecar and excluded from the agent environment. The agent receives proxy-routing base URLs instead. See docs/awf-config-spec.md \u00a79 for credential isolation semantics."
"description": "Enable the API proxy sidecar container. When enabled, source credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, COPILOT_GITHUB_TOKEN, COPILOT_PROVIDER_API_KEY, GEMINI_API_KEY) are held exclusively in the sidecar and excluded from the agent environment. The agent receives proxy-routing base URLs instead. See docs/awf-config-spec.md §9 for credential isolation semantics."
},
"enableTokenSteering": {
"type": "boolean",
Expand All @@ -70,11 +70,11 @@
"maxEffectiveTokens": {
"type": "integer",
"minimum": 1,
"description": "Maximum cumulative effective tokens allowed for a run. When reached, the API proxy rejects subsequent requests with HTTP 429 and error type 'effective_tokens_limit_exceeded'. Tokens are weighted: input \u00d71, cache-read \u00d70.1, output \u00d74, reasoning \u00d74. See spec \u00a710."
"description": "Maximum cumulative effective tokens allowed for a run. When reached, the API proxy rejects subsequent requests with HTTP 429 and error type 'effective_tokens_limit_exceeded'. Tokens are weighted: input ×1, cache-read ×0.1, output ×4, reasoning ×4. See spec §10."
},
"modelMultipliers": {
"type": "object",
"description": "Per-model multipliers for effective token accounting. Each model's weighted tokens are multiplied by this value before accumulation. Unlisted models use defaultModelMultiplier when set, otherwise the highest configured multiplier. See spec \u00a710.2.",
"description": "Per-model multipliers for effective token accounting. Each model's weighted tokens are multiplied by this value before accumulation. Unlisted models use defaultModelMultiplier when set, otherwise the highest configured multiplier. See spec §10.2.",
"additionalProperties": {
"type": "number",
"exclusiveMinimum": 0
Expand All @@ -93,7 +93,7 @@
"maxRuns": {
"type": "integer",
"minimum": 1,
"description": "Maximum number of LLM invocations allowed for a run. When reached, the API proxy rejects subsequent requests with HTTP 429 and error type 'max_runs_exceeded'. See spec \u00a711."
"description": "Maximum number of LLM invocations allowed for a run. When reached, the API proxy rejects subsequent requests with HTTP 429 and error type 'max_runs_exceeded'. See spec §11."
},
"maxPermissionDenied": {
"type": "integer",
Expand Down Expand Up @@ -183,7 +183,7 @@
},
"auth": {
"type": "object",
"description": "Authentication configuration for the API proxy sidecar. Enables OIDC-based credential exchange (e.g., GitHub OIDC \u2192 Azure AD, AWS STS, GCP Workload Identity, or Anthropic Workload Identity Federation). See docs/awf-config-spec.md \u00a79.5.",
"description": "Authentication configuration for the API proxy sidecar. Enables OIDC-based credential exchange (e.g., GitHub OIDC Azure AD, AWS STS, GCP Workload Identity, or Anthropic Workload Identity Federation). See docs/awf-config-spec.md §9.5.",
"additionalProperties": false,
"properties": {
"type": {
Expand Down Expand Up @@ -480,12 +480,16 @@
"dockerHostPathPrefix": {
"type": "string",
"description": "Prefix bind-mount source paths so the Docker daemon can resolve runner filesystem paths. Required for ARC DinD sidecar runners where the runner and daemon have separate filesystems. Example: \"/host\". Kernel virtual filesystems (/dev, /sys, /proc) are automatically excluded from prefixing. When this points at a daemon-visible shared /tmp path, AWF also stages the invoking CLI binary plus /etc/passwd, /etc/group, and the generated chroot /etc/hosts there."
},
"runnerToolCachePath": {
"type": "string",
"description": "Host runner tool cache directory to mount read-only into chroot mode. When set, AWF checks this path first before environment-based auto-detection."
}
}
},
"environment": {
"type": "object",
"description": "Environment variable propagation into the agent container. Merge behavior is: AWF-reserved variables are set by AWF and are not overridden by envAll or envFile; if envAll is true, host environment variables are forwarded next; envFile is then applied only for variables not already present, so it does not override envAll; CLI -e/--env has highest precedence and may override any variable, including AWF-reserved ones. When apiProxy.enabled is true, source credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) are excluded from the agent and held in the API proxy sidecar. See docs/awf-config-spec.md \u00a78\u20139 for credential isolation rules.",
"description": "Environment variable propagation into the agent container. Merge behavior is: AWF-reserved variables are set by AWF and are not overridden by envAll or envFile; if envAll is true, host environment variables are forwarded next; envFile is then applied only for variables not already present, so it does not override envAll; CLI -e/--env has highest precedence and may override any variable, including AWF-reserved ones. When apiProxy.enabled is true, source credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) are excluded from the agent and held in the API proxy sidecar. See docs/awf-config-spec.md §8–9 for credential isolation rules.",
"additionalProperties": false,
"properties": {
"envFile": {
Expand All @@ -494,7 +498,7 @@
},
"envAll": {
"type": "boolean",
"description": "Forward all host environment variables into the agent container. Use with caution \u2014 may expose secrets."
"description": "Forward all host environment variables into the agent container. Use with caution may expose secrets."
},
"excludeEnv": {
"type": "array",
Expand Down
18 changes: 11 additions & 7 deletions src/awf-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable the API proxy sidecar container. When enabled, source credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, COPILOT_GITHUB_TOKEN, COPILOT_PROVIDER_API_KEY, GEMINI_API_KEY) are held exclusively in the sidecar and excluded from the agent environment. The agent receives proxy-routing base URLs instead. See docs/awf-config-spec.md \u00a79 for credential isolation semantics."
"description": "Enable the API proxy sidecar container. When enabled, source credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, COPILOT_GITHUB_TOKEN, COPILOT_PROVIDER_API_KEY, GEMINI_API_KEY) are held exclusively in the sidecar and excluded from the agent environment. The agent receives proxy-routing base URLs instead. See docs/awf-config-spec.md §9 for credential isolation semantics."
},
"enableTokenSteering": {
"type": "boolean",
Expand All @@ -70,11 +70,11 @@
"maxEffectiveTokens": {
"type": "integer",
"minimum": 1,
"description": "Maximum cumulative effective tokens allowed for a run. When reached, the API proxy rejects subsequent requests with HTTP 429 and error type 'effective_tokens_limit_exceeded'. Tokens are weighted: input \u00d71, cache-read \u00d70.1, output \u00d74, reasoning \u00d74. See spec \u00a710."
"description": "Maximum cumulative effective tokens allowed for a run. When reached, the API proxy rejects subsequent requests with HTTP 429 and error type 'effective_tokens_limit_exceeded'. Tokens are weighted: input ×1, cache-read ×0.1, output ×4, reasoning ×4. See spec §10."
},
"modelMultipliers": {
"type": "object",
"description": "Per-model multipliers for effective token accounting. Each model's weighted tokens are multiplied by this value before accumulation. Unlisted models use defaultModelMultiplier when set, otherwise the highest configured multiplier. See spec \u00a710.2.",
"description": "Per-model multipliers for effective token accounting. Each model's weighted tokens are multiplied by this value before accumulation. Unlisted models use defaultModelMultiplier when set, otherwise the highest configured multiplier. See spec §10.2.",
"additionalProperties": {
"type": "number",
"exclusiveMinimum": 0
Expand All @@ -93,7 +93,7 @@
"maxRuns": {
"type": "integer",
"minimum": 1,
"description": "Maximum number of LLM invocations allowed for a run. When reached, the API proxy rejects subsequent requests with HTTP 429 and error type 'max_runs_exceeded'. See spec \u00a711."
"description": "Maximum number of LLM invocations allowed for a run. When reached, the API proxy rejects subsequent requests with HTTP 429 and error type 'max_runs_exceeded'. See spec §11."
},
"maxPermissionDenied": {
"type": "integer",
Expand Down Expand Up @@ -183,7 +183,7 @@
},
"auth": {
"type": "object",
"description": "Authentication configuration for the API proxy sidecar. Enables OIDC-based credential exchange (e.g., GitHub OIDC \u2192 Azure AD, AWS STS, GCP Workload Identity, or Anthropic Workload Identity Federation). See docs/awf-config-spec.md \u00a79.5.",
"description": "Authentication configuration for the API proxy sidecar. Enables OIDC-based credential exchange (e.g., GitHub OIDC Azure AD, AWS STS, GCP Workload Identity, or Anthropic Workload Identity Federation). See docs/awf-config-spec.md §9.5.",
"additionalProperties": false,
"properties": {
"type": {
Expand Down Expand Up @@ -480,12 +480,16 @@
"dockerHostPathPrefix": {
"type": "string",
"description": "Prefix bind-mount source paths so the Docker daemon can resolve runner filesystem paths. Required for ARC DinD sidecar runners where the runner and daemon have separate filesystems. Example: \"/host\". Kernel virtual filesystems (/dev, /sys, /proc) are automatically excluded from prefixing. When this points at a daemon-visible shared /tmp path, AWF also stages the invoking CLI binary plus /etc/passwd, /etc/group, and the generated chroot /etc/hosts there."
},
"runnerToolCachePath": {
"type": "string",
"description": "Host runner tool cache directory to mount read-only into chroot mode. When set, AWF checks this path first before environment-based auto-detection."
}
}
},
"environment": {
"type": "object",
"description": "Environment variable propagation into the agent container. Merge behavior is: AWF-reserved variables are set by AWF and are not overridden by envAll or envFile; if envAll is true, host environment variables are forwarded next; envFile is then applied only for variables not already present, so it does not override envAll; CLI -e/--env has highest precedence and may override any variable, including AWF-reserved ones. When apiProxy.enabled is true, source credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) are excluded from the agent and held in the API proxy sidecar. See docs/awf-config-spec.md \u00a78\u20139 for credential isolation rules.",
"description": "Environment variable propagation into the agent container. Merge behavior is: AWF-reserved variables are set by AWF and are not overridden by envAll or envFile; if envAll is true, host environment variables are forwarded next; envFile is then applied only for variables not already present, so it does not override envAll; CLI -e/--env has highest precedence and may override any variable, including AWF-reserved ones. When apiProxy.enabled is true, source credentials (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) are excluded from the agent and held in the API proxy sidecar. See docs/awf-config-spec.md §8–9 for credential isolation rules.",
"additionalProperties": false,
"properties": {
"envFile": {
Expand All @@ -494,7 +498,7 @@
},
"envAll": {
"type": "boolean",
"description": "Forward all host environment variables into the agent container. Use with caution \u2014 may expose secrets."
"description": "Forward all host environment variables into the agent container. Use with caution may expose secrets."
},
"excludeEnv": {
"type": "array",
Expand Down
7 changes: 7 additions & 0 deletions src/commands/build-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,13 @@ describe('buildConfig', () => {
expect(config.dockerHostPathPrefix).toBe('/host');
});

it('should pass through runnerToolCachePath', () => {
const config = buildConfig(makeInputs({
options: { ...makeInputs().options, runnerToolCachePath: '/opt/hostedtoolcache' },
}));
expect(config.runnerToolCachePath).toBe('/opt/hostedtoolcache');
});

it('should pass through modelAliases', () => {
const aliases = { 'gpt-4': ['gpt-4-turbo'] };
const config = buildConfig(makeInputs({ modelAliases: aliases }));
Expand Down
1 change: 1 addition & 0 deletions src/commands/build-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export function buildConfig(inputs: BuildConfigInputs): WrapperConfig {
auditDir: (options.auditDir as string | undefined) || process.env.AWF_AUDIT_DIR,
sessionStateDir:
(options.sessionStateDir as string | undefined) || process.env.AWF_SESSION_STATE_DIR,
runnerToolCachePath: options.runnerToolCachePath as string | undefined,
enableHostAccess: options.enableHostAccess as boolean,
localhostDetected,
allowHostPorts: options.allowHostPorts as string | undefined,
Expand Down
2 changes: 2 additions & 0 deletions src/config-file-mapping.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ describe('mapAwfFileConfigToCliOptions', () => {
tty: true,
dockerHost: 'unix:///var/run/docker.sock',
dockerHostPathPrefix: '/host',
runnerToolCachePath: '/opt/hostedtoolcache',
},
});

Expand All @@ -270,6 +271,7 @@ describe('mapAwfFileConfigToCliOptions', () => {
expect(result.tty).toBe(true);
expect(result.dockerHost).toBe('unix:///var/run/docker.sock');
expect(result.dockerHostPathPrefix).toBe('/host');
expect(result.runnerToolCachePath).toBe('/opt/hostedtoolcache');
});

it('maps environment fields', () => {
Expand Down
5 changes: 5 additions & 0 deletions src/config-file-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,11 @@ describe('validateAwfFileConfig', () => {
expect(errors).toContain('config.container.dockerHostPathPrefix must be a string');
});

it('rejects non-string container.runnerToolCachePath', () => {
const errors = validateAwfFileConfig({ container: { runnerToolCachePath: 123 } });
expect(errors).toContain('config.container.runnerToolCachePath must be a string');
});

it('rejects unknown container keys', () => {
const errors = validateAwfFileConfig({ container: { unknown: true } });
expect(errors).toContain('config.container.unknown is not supported');
Expand Down
2 changes: 2 additions & 0 deletions src/config-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ interface AwfFileConfig {
tty?: boolean;
dockerHost?: string;
dockerHostPathPrefix?: string;
runnerToolCachePath?: string;
};
environment?: {
envFile?: string;
Expand Down Expand Up @@ -242,6 +243,7 @@ export function mapAwfFileConfigToCliOptions(config: AwfFileConfig): Record<stri
tty: config.container?.tty,
dockerHost: config.container?.dockerHost,
dockerHostPathPrefix: config.container?.dockerHostPathPrefix,
runnerToolCachePath: config.container?.runnerToolCachePath,

envFile: config.environment?.envFile,
envAll: config.environment?.envAll,
Expand Down
5 changes: 5 additions & 0 deletions src/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ describe('awf-config.schema.json', () => {
expect(validate({ container: { agentTimeout: 1 } })).toBe(true);
});

it('accepts container.runnerToolCachePath as a string', () => {
expect(validate({ container: { runnerToolCachePath: '/opt/hostedtoolcache' } })).toBe(true);
expect(validate({ container: { runnerToolCachePath: 123 } })).toBe(false);
});

it('rejects non-positive-integer rateLimiting values', () => {
expect(validate({ rateLimiting: { requestsPerMinute: 0 } })).toBe(false);
expect(validate({ rateLimiting: { requestsPerMinute: 1 } })).toBe(true);
Expand Down
Loading
Loading