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
18 changes: 15 additions & 3 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,12 @@ sudo awf \
- Location: `/tmp/awf-agent-logs-<timestamp>/`
- View with: `cat /tmp/awf-agent-logs-<timestamp>/*.log`

**Agent Session State:**
- Contains structured conversation data written by Copilot CLI (e.g., `events.jsonl`)
- Location: `/tmp/awf-agent-session-state-<timestamp>/`
- View with: `cat /tmp/awf-agent-session-state-<timestamp>/events.jsonl`
- Useful for triage dashboards, benchmarking, and debugging Copilot CLI runs

**Squid Logs:**
- Contains all HTTP/HTTPS traffic (allowed and denied)
- Location: `/tmp/squid-logs-<timestamp>/`
Expand All @@ -859,9 +865,15 @@ sudo cat /tmp/squid-logs-<timestamp>/access.log
```

**How it works:**
- GitHub Copilot CLI writes to `~/.copilot/logs/`, Squid writes to `/var/log/squid/`
- Volume mounts map these to `${workDir}/agent-logs/` and `${workDir}/squid-logs/`
- Before cleanup, logs are automatically moved to `/tmp/awf-agent-logs-<timestamp>/` and `/tmp/squid-logs-<timestamp>/` (if they exist)
- GitHub Copilot CLI writes to `~/.copilot/logs/` and `~/.copilot/session-state/`; Squid writes to `/var/log/squid/`
- Volume mounts map container paths to:
- `${workDir}/agent-logs/` → `~/.copilot/logs/`
- `${workDir}/agent-session-state/` → `~/.copilot/session-state/`
- `${workDir}/squid-logs/` → `/var/log/squid/`
- Before cleanup, non-empty directories are automatically moved to timestamped `/tmp` paths:
- `/tmp/awf-agent-logs-<timestamp>/`
- `/tmp/awf-agent-session-state-<timestamp>/`
- `/tmp/squid-logs-<timestamp>/`
Comment on lines 867 to +876
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “How it works” section describes mounts for ~/.copilot/session-state, but in AWF chroot mode the agent command runs inside /host (entrypoint.sh), so the effective path being written is under /host$HOME/.... Once the mount points are corrected, please update this section to reflect the chroot behavior (or clarify that the mount targets both chroot and non-chroot paths).

Copilot uses AI. Check for mistakes.
- Empty log directories are not preserved (avoids cluttering /tmp)

### Keep Containers for Inspection
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions src/docker-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,8 @@ export function generateDockerCompose(
`${workspaceDir}:${workspaceDir}:rw`,
// Mount agent logs directory to workDir for persistence
`${config.workDir}/agent-logs:${effectiveHome}/.copilot/logs:rw`,
// Mount agent session-state directory to workDir for persistence (events.jsonl)
`${config.workDir}/agent-session-state:${effectiveHome}/.copilot/session-state:rw`,
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The session-state volume is mounted to ${effectiveHome}/.copilot/session-state, but when AWF runs in chroot mode the user command writes to paths under /host (see entrypoint.sh chroot execution). As a result, ~/.copilot/session-state inside the chroot won’t see this mount and events.jsonl may still be discarded. Consider mounting the same host dir to /host${effectiveHome}/.copilot/session-state (and/or ensuring Copilot is configured to write to the non-chroot path).

This issue also appears in the following locations of the same file:

  • line 1553
  • line 2116
Suggested change
`${config.workDir}/agent-session-state:${effectiveHome}/.copilot/session-state:rw`,
`${config.workDir}/agent-session-state:${effectiveHome}/.copilot/session-state:rw`,
// When running in chroot mode, the user's home is accessed under /host,
// so also mount the same session-state directory to the chrooted home path.
`${config.workDir}/agent-session-state:/host${effectiveHome}/.copilot/session-state:rw`,

Copilot uses AI. Check for mistakes.
// Init signal volume for iptables init container coordination
`${initSignalDir}:/tmp/awf-init:rw`,
];
Expand Down Expand Up @@ -1548,6 +1550,13 @@ export async function writeConfigs(config: WrapperConfig): Promise<void> {
}
logger.debug(`Agent logs directory created at: ${agentLogsDir}`);

// Create agent session-state directory for persistence (events.jsonl written by Copilot CLI)
const agentSessionStateDir = path.join(config.workDir, 'agent-session-state');
if (!fs.existsSync(agentSessionStateDir)) {
fs.mkdirSync(agentSessionStateDir, { recursive: true });
}
logger.debug(`Agent session-state directory created at: ${agentSessionStateDir}`);
Comment on lines +1553 to +1558
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior (creating agent-session-state, preserving it on cleanup, and the new volume mount) isn’t covered by tests. src/docker-manager.test.ts already has coverage for the analogous agent-logs preservation; please add similar assertions for session-state so regressions are caught.

Copilot uses AI. Check for mistakes.

// Create squid logs directory for persistence
// If proxyLogsDir is specified, write directly there (timeout-safe)
// Otherwise, use workDir/squid-logs (will be moved to /tmp after cleanup)
Expand Down Expand Up @@ -2104,6 +2113,18 @@ export async function cleanup(workDir: string, keepFiles: boolean, proxyLogsDir?
}
}

// Preserve agent session-state before cleanup (contains events.jsonl from Copilot CLI)
const agentSessionStateDir = path.join(workDir, 'agent-session-state');
const agentSessionStateDestination = path.join(os.tmpdir(), `awf-agent-session-state-${timestamp}`);
if (fs.existsSync(agentSessionStateDir) && fs.readdirSync(agentSessionStateDir).length > 0) {
try {
fs.renameSync(agentSessionStateDir, agentSessionStateDestination);
logger.info(`Agent session state preserved at: ${agentSessionStateDestination}`);
} catch (error) {
logger.debug('Could not preserve agent session state:', error);
}
}

// Preserve api-proxy logs before cleanup
if (proxyLogsDir) {
// Logs were written directly to sibling of proxyLogsDir during runtime (timeout-safe)
Expand Down
Loading