@technomoron/agent-run 0.99.44 → 0.99.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES +10 -0
- package/README.md +32 -4
- package/dist/cli.js +9 -6
- package/dist/commands.js +4 -3
- package/dist/project.js +1 -0
- package/dist/runtime/clean-sessions.js +16 -2
- package/ops/systemd/ai-tools-update.service +1 -0
- package/package.json +5 -2
- package/scripts/cleanup-agent-sessions.sh +27 -0
- package/scripts/install-systemd-jobs.sh +2 -0
- package/scripts/install-windows-cleanup.ps1 +14 -0
- package/scripts/run-windows-cleanup.ps1 +23 -0
package/CHANGES
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
CHANGES
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
Version 0.99.45 (2026-10-14)
|
|
5
|
+
----------------------------
|
|
6
|
+
* Move automatic session cleanup out of interactive startup and exit into
|
|
7
|
+
scheduled maintenance, using the hourly AI tools timer on Linux.
|
|
8
|
+
* Add --clean-old and per-user cleanup.env retention settings, defaulting to
|
|
9
|
+
seven days; set AGENT_RUN_SESSION_RETENTION_DAYS=0 to disable retention cleanup.
|
|
10
|
+
* Add hourly Windows session cleanup as a hidden, unelevated scheduled task.
|
|
11
|
+
* Run Linux cleanup as explicitly selected normal users and preserve native
|
|
12
|
+
session deletion and history maintenance.
|
|
13
|
+
|
|
4
14
|
Version 0.99.44 (2026-10-14)
|
|
5
15
|
----------------------------
|
|
6
16
|
* Remove local agent sessions last modified more than seven days ago before
|
package/README.md
CHANGED
|
@@ -290,10 +290,19 @@ Global flags:
|
|
|
290
290
|
`agent-run codex --help`, `agent-run claude --help`, `agent-run gemini --help`,
|
|
291
291
|
and `agent-run grok --help` pass `--help` through to the underlying tool.
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
293
|
+
Session cleanup runs separately from interactive agent startup and exit. The
|
|
294
|
+
hourly AI tool timer cleans sessions older than seven days by default for selected
|
|
295
|
+
users. Set retention in `~/.agent-run/cleanup.env`:
|
|
296
|
+
|
|
297
|
+
```sh
|
|
298
|
+
AGENT_RUN_SESSION_RETENTION_DAYS=7
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Use a non-negative whole number of days; `0` disables retention cleanup.
|
|
302
|
+
An environment value overrides the file. `--configdir PATH` selects another
|
|
303
|
+
configuration root and its `cleanup.env`. Sessions exactly at the retention
|
|
304
|
+
boundary are retained. Authentication, settings, skills and brain knowledge are
|
|
305
|
+
preserved. Run retention cleanup manually with `agent-run --clean-old all`.
|
|
297
306
|
|
|
298
307
|
Delete all saved sessions for selected agents without launching an agent:
|
|
299
308
|
|
|
@@ -1155,6 +1164,25 @@ starts at boot without an interactive login, and restarts it to load the update.
|
|
|
1155
1164
|
No accounts are selected by default. The service remains owned by the selected
|
|
1156
1165
|
user and listens on that user's private Unix socket.
|
|
1157
1166
|
|
|
1167
|
+
After a successful timer update, session cleanup runs as each selected user.
|
|
1168
|
+
Set `AI_TOOLS_CLEANUP_USERS="bjorn"` in `/etc/default/ai-tools-update` to select
|
|
1169
|
+
accounts; if unset, it uses `AI_TOOLS_BRAIN_USERS`. An explicitly empty value
|
|
1170
|
+
disables scheduled cleanup. Each user's `~/.agent-run/cleanup.env` controls
|
|
1171
|
+
retention, defaulting to seven days. Failures appear in the systemd journal.
|
|
1172
|
+
|
|
1173
|
+
On Windows, install hourly cleanup for the current user from PowerShell:
|
|
1174
|
+
|
|
1175
|
+
```powershell
|
|
1176
|
+
$prefix = npm.cmd prefix -g
|
|
1177
|
+
& "$prefix\node_modules\@technomoron\agent-run\scripts\install-windows-cleanup.ps1"
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
The `Agent Session Cleanup` task runs hidden without elevation while the user is
|
|
1181
|
+
signed in, starting ten minutes after installation and repeating hourly. It uses
|
|
1182
|
+
the same `cleanup.env` and seven-day default. Pass `-ConfigRoot PATH` to select
|
|
1183
|
+
another configuration tree. Its latest output is in
|
|
1184
|
+
`<config-root>/runtime/cleanup.log`. The task skips overlapping runs.
|
|
1185
|
+
|
|
1158
1186
|
Node 24 or newer must be installed at `/usr/local/bin/node` before running the
|
|
1159
1187
|
updater. `AI_TOOLS_AGENT_RUN_PACKAGE` can select a package version or a
|
|
1160
1188
|
root-owned local package archive while testing an unpublished build; it defaults
|
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ function parseInvocation(invokedTool, argv) {
|
|
|
12
12
|
let command = normalizeCommandName(invokedTool);
|
|
13
13
|
const options = extractGlobalOptions(argv);
|
|
14
14
|
applyGlobalOptions(options);
|
|
15
|
-
if (command === null &&
|
|
15
|
+
if (command === null && options.args[0] && /^(--clean|--clean-old)(=|$)/.test(options.args[0])) {
|
|
16
16
|
return parseCleanCommand(options.args);
|
|
17
17
|
}
|
|
18
18
|
if (command === null) {
|
|
@@ -22,15 +22,17 @@ function parseInvocation(invokedTool, argv) {
|
|
|
22
22
|
}
|
|
23
23
|
function parseCleanCommand(args) {
|
|
24
24
|
const flag = args[0];
|
|
25
|
+
const olderOnly = flag === '--clean-old' || flag.startsWith('--clean-old=');
|
|
26
|
+
const name = olderOnly ? '--clean-old' : '--clean';
|
|
25
27
|
const values = [
|
|
26
|
-
...(flag.includes('=') ? [flag.slice(
|
|
28
|
+
...(flag.includes('=') ? [flag.slice(name.length + 1)] : []),
|
|
27
29
|
...args.slice(1)
|
|
28
30
|
].flatMap((value) => value.split(','));
|
|
29
31
|
if (!values.length || values.some((value) => value !== 'all' && !types_1.AGENT_IDS.includes(value))
|
|
30
32
|
|| (values.includes('all') && values.length !== 1)) {
|
|
31
|
-
(0, utils_1.fail)(
|
|
33
|
+
(0, utils_1.fail)(`${name} requires all or a list of codex, claude, gemini, grok`);
|
|
32
34
|
}
|
|
33
|
-
return { command: 'clean', agents: values[0] === 'all' ? [...types_1.AGENT_IDS] : [...new Set(values)] };
|
|
35
|
+
return { command: 'clean', agents: values[0] === 'all' ? [...types_1.AGENT_IDS] : [...new Set(values)], ...(olderOnly ? { olderOnly: true } : {}) };
|
|
34
36
|
}
|
|
35
37
|
function applyGlobalOptions(options) {
|
|
36
38
|
if (options.verbose) {
|
|
@@ -173,8 +175,8 @@ function parseRunCommand(command, inputArgs) {
|
|
|
173
175
|
const args = [];
|
|
174
176
|
let passthrough = false;
|
|
175
177
|
for (const arg of inputArgs) {
|
|
176
|
-
if (!passthrough && (
|
|
177
|
-
(0, utils_1.fail)('Use --clean on its own: agent-run --clean all|codex,claude,gemini,grok');
|
|
178
|
+
if (!passthrough && /^(--clean|--clean-old)(=|$)/.test(arg))
|
|
179
|
+
(0, utils_1.fail)('Use --clean or --clean-old on its own: agent-run --clean-old all|codex,claude,gemini,grok');
|
|
178
180
|
if (passthrough) {
|
|
179
181
|
args.push(arg);
|
|
180
182
|
continue;
|
|
@@ -400,6 +402,7 @@ function renderHelp(topic) {
|
|
|
400
402
|
' grok [--none] [--create] [--local] [--show] [--generate] [--yolo|--sandboxed] [args...]',
|
|
401
403
|
' Run grok with generated private config',
|
|
402
404
|
' --clean all|AGENTS Delete saved sessions for selected agents',
|
|
405
|
+
' --clean-old all|AGENTS Delete sessions older than configured retention (7 days)',
|
|
403
406
|
' compress [--agent NAME] [--scope SCOPE] [--dry-run] Consolidate brain knowledge',
|
|
404
407
|
' setup [org/repo] Install the default tree and selected profile',
|
|
405
408
|
' check [--all] [path] Validate generated profile output',
|
package/dist/commands.js
CHANGED
|
@@ -27,9 +27,11 @@ function main(invokedTool, argv) {
|
|
|
27
27
|
}
|
|
28
28
|
function dispatch(command) {
|
|
29
29
|
switch (command.command) {
|
|
30
|
-
case 'clean':
|
|
31
|
-
|
|
30
|
+
case 'clean': {
|
|
31
|
+
const root = (0, project_1.defaultConfigRoot)(process.cwd());
|
|
32
|
+
(0, clean_sessions_1.reportCleanup)((0, clean_sessions_1.cleanSessions)(root, command.agents, !command.olderOnly, Date.now(), command.olderOnly ? (0, clean_sessions_1.sessionRetentionDays)(root) : 7), true);
|
|
32
33
|
return;
|
|
34
|
+
}
|
|
33
35
|
case 'compress':
|
|
34
36
|
void runCompress(command).catch((error) => { process.stderr.write(`agent-run: ${(0, utils_1.formatError)(error)}\n`); process.exitCode = 1; });
|
|
35
37
|
return;
|
|
@@ -155,7 +157,6 @@ async function runTool(parsed) {
|
|
|
155
157
|
if (!runtime) {
|
|
156
158
|
(0, utils_1.fail)(`no generated ${command} runtime found for profile ${rendered.profile}`);
|
|
157
159
|
}
|
|
158
|
-
(0, clean_sessions_1.reportCleanup)((0, clean_sessions_1.cleanSessions)(configRoot));
|
|
159
160
|
(0, spawn_agent_1.spawnAgent)(adapter.spawn(runtime, { binary: realBinary, passthroughArgs: args, wrapperArgs }));
|
|
160
161
|
}
|
|
161
162
|
function runStatus() {
|
package/dist/project.js
CHANGED
|
@@ -12,6 +12,7 @@ exports.resolveProfile = resolveProfile;
|
|
|
12
12
|
exports.resolveProfileResult = resolveProfileResult;
|
|
13
13
|
exports.parseProfile = parseProfile;
|
|
14
14
|
exports.projectRootForProfile = projectRootForProfile;
|
|
15
|
+
exports.parseEnvFile = parseEnvFile;
|
|
15
16
|
exports.defaultConfigRoot = defaultConfigRoot;
|
|
16
17
|
const childProcess = require("child_process");
|
|
17
18
|
const fs = require("fs");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sessionRetentionDays = sessionRetentionDays;
|
|
3
4
|
exports.cleanSessions = cleanSessions;
|
|
4
5
|
exports.reportCleanup = reportCleanup;
|
|
5
6
|
const fs = require("node:fs");
|
|
@@ -14,6 +15,17 @@ const manifest_1 = require("../manifest");
|
|
|
14
15
|
const templates_1 = require("../templates");
|
|
15
16
|
const project_1 = require("../project");
|
|
16
17
|
const WEEK = 7 * 24 * 60 * 60 * 1000;
|
|
18
|
+
const DAY = WEEK / 7;
|
|
19
|
+
function sessionRetentionDays(configRoot) {
|
|
20
|
+
const file = path.join(configRoot, 'cleanup.env');
|
|
21
|
+
const settings = fs.existsSync(file) ? (0, project_1.parseEnvFile)(fs.readFileSync(file, 'utf8')) : {};
|
|
22
|
+
const value = process.env.AGENT_RUN_SESSION_RETENTION_DAYS ?? settings.AGENT_RUN_SESSION_RETENTION_DAYS ?? '7';
|
|
23
|
+
const days = Number(value);
|
|
24
|
+
if (!/^\d+$/.test(value) || !Number.isSafeInteger(days * DAY)) {
|
|
25
|
+
throw new Error('AGENT_RUN_SESSION_RETENTION_DAYS must be a non-negative whole number of days (0 disables retention cleanup).');
|
|
26
|
+
}
|
|
27
|
+
return days;
|
|
28
|
+
}
|
|
17
29
|
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
18
30
|
// Do not follow symlinks, including symlinked parent directories or another user's home.
|
|
19
31
|
function owned(file) {
|
|
@@ -160,9 +172,11 @@ function pruneIndexes(home, agent, ids) {
|
|
|
160
172
|
}
|
|
161
173
|
}
|
|
162
174
|
}
|
|
163
|
-
function cleanSessions(configRoot, agents = types_1.AGENT_IDS, all = false, now = Date.now()) {
|
|
175
|
+
function cleanSessions(configRoot, agents = types_1.AGENT_IDS, all = false, now = Date.now(), retentionDays = 7) {
|
|
164
176
|
return agents.map((agent) => {
|
|
165
177
|
const result = { agent, removed: 0, errors: [] };
|
|
178
|
+
if (!all && retentionDays === 0)
|
|
179
|
+
return result;
|
|
166
180
|
let directories;
|
|
167
181
|
try {
|
|
168
182
|
directories = homes(configRoot, agent);
|
|
@@ -177,7 +191,7 @@ function cleanSessions(configRoot, agents = types_1.AGENT_IDS, all = false, now
|
|
|
177
191
|
continue;
|
|
178
192
|
const removed = new Set();
|
|
179
193
|
for (const session of fileSessions(home, agent)) {
|
|
180
|
-
if (!all && session.modified >= now -
|
|
194
|
+
if (!all && session.modified >= now - retentionDays * DAY)
|
|
181
195
|
continue;
|
|
182
196
|
if ([process.env.CODEX_THREAD_ID, process.env.CODEX_SESSION_ID, process.env.CLAUDE_SESSION_ID, process.env.GROK_SESSION_ID].includes(session.id)) {
|
|
183
197
|
if (all)
|
|
@@ -15,3 +15,4 @@ Environment=PNPM_HOME=/usr/local
|
|
|
15
15
|
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
16
16
|
EnvironmentFile=-/etc/default/ai-tools-update
|
|
17
17
|
ExecStart=/usr/local/libexec/agent-run/update-ai-tools
|
|
18
|
+
ExecStartPost=/usr/local/libexec/agent-run/cleanup-agent-sessions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@technomoron/agent-run",
|
|
3
|
-
"version": "0.99.
|
|
3
|
+
"version": "0.99.45",
|
|
4
4
|
"packageManager": "pnpm@10.34.5",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agent-run": "dist/agent-run.js",
|
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
"scripts/install-systemd-jobs.sh",
|
|
18
18
|
"scripts/update-ai-tools.sh",
|
|
19
19
|
"scripts/ensure-agent-brain.sh",
|
|
20
|
+
"scripts/cleanup-agent-sessions.sh",
|
|
20
21
|
"scripts/brain-pipe-security.ps1",
|
|
21
22
|
"scripts/install-windows-brain.ps1",
|
|
23
|
+
"scripts/install-windows-cleanup.ps1",
|
|
24
|
+
"scripts/run-windows-cleanup.ps1",
|
|
22
25
|
"scripts/run-windows-brain.ps1",
|
|
23
26
|
"scripts/run-hidden.vbs",
|
|
24
27
|
"README.md",
|
|
@@ -36,7 +39,7 @@
|
|
|
36
39
|
"cleanbuild": "run-s clean:dist build",
|
|
37
40
|
"prepack": "run-s build",
|
|
38
41
|
"test": "run-s build test:codex-profiles test:integration test:release",
|
|
39
|
-
"test:codex-profiles": "node --test scripts/test-codex-profiles.cjs scripts/test-session-cleanup.cjs",
|
|
42
|
+
"test:codex-profiles": "node --test scripts/test-codex-profiles.cjs scripts/test-session-cleanup.cjs scripts/test-windows-cleanup.cjs",
|
|
40
43
|
"test:brain": "node --test scripts/test-brain.cjs",
|
|
41
44
|
"test:integration": "bash ./scripts/test.sh",
|
|
42
45
|
"test:release": "bash ./scripts/test-release.sh",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [ "$(id -u)" -ne 0 ]; then
|
|
5
|
+
echo "cleanup-agent-sessions.sh must run as root" >&2
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
# Select accounts explicitly; never scan every home or run native CLIs as root.
|
|
10
|
+
read -r -a accounts <<<"${AI_TOOLS_CLEANUP_USERS-${AI_TOOLS_BRAIN_USERS:-}}"
|
|
11
|
+
status=0
|
|
12
|
+
for account in "${accounts[@]}"; do
|
|
13
|
+
entry="$(getent passwd "$account")" || { echo "Unknown cleanup account: $account" >&2; status=1; continue; }
|
|
14
|
+
IFS=: read -r username password uid gid gecos account_home login_shell <<<"$entry"
|
|
15
|
+
if [ "$uid" -lt 1000 ] || [ "$uid" -eq 65534 ]; then
|
|
16
|
+
echo "Refusing to clean sessions for system account: $account" >&2
|
|
17
|
+
status=1
|
|
18
|
+
continue
|
|
19
|
+
fi
|
|
20
|
+
# A clean environment avoids leaking root's home, session IDs or native settings.
|
|
21
|
+
if ! runuser -u "$username" -- env -i "HOME=$account_home" "USER=$username" "LOGNAME=$username" \
|
|
22
|
+
PATH=/usr/local/bin:/usr/bin:/bin /bin/sh -c 'cd "$HOME" && exec "$@"' cleanup-agent-sessions /usr/local/bin/agent-run \
|
|
23
|
+
--configdir "$account_home/.agent-run" --clean-old all; then
|
|
24
|
+
status=1
|
|
25
|
+
fi
|
|
26
|
+
done
|
|
27
|
+
exit "$status"
|
|
@@ -29,6 +29,7 @@ SERVICE_FILE="$ROOT/ops/systemd/ai-tools-update.service"
|
|
|
29
29
|
TIMER_FILE="$ROOT/ops/systemd/ai-tools-update.timer"
|
|
30
30
|
BRAIN_HELPER="$ROOT/scripts/ensure-agent-brain.sh"
|
|
31
31
|
BRAIN_SERVICE="$ROOT/ops/systemd/agent-brain.service"
|
|
32
|
+
CLEANUP_HELPER="$ROOT/scripts/cleanup-agent-sessions.sh"
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
INSTALL_AI_TOOLS=0
|
|
@@ -82,6 +83,7 @@ run() {
|
|
|
82
83
|
run install -d -m 0755 "$INSTALL_LIBEXEC_DIR" "$SYSTEMD_DIR" "$SYSTEMD_USER_DIR"
|
|
83
84
|
run install -m 0755 "$UPDATE_SCRIPT" "$INSTALL_LIBEXEC_DIR/update-ai-tools"
|
|
84
85
|
run install -m 0755 "$BRAIN_HELPER" "$INSTALL_LIBEXEC_DIR/ensure-agent-brain"
|
|
86
|
+
run install -m 0755 "$CLEANUP_HELPER" "$INSTALL_LIBEXEC_DIR/cleanup-agent-sessions"
|
|
85
87
|
run install -m 0644 "$BRAIN_SERVICE" "$SYSTEMD_USER_DIR/agent-brain.service"
|
|
86
88
|
run install -m 0644 "$SERVICE_FILE" "$SYSTEMD_DIR/ai-tools-update.service"
|
|
87
89
|
run install -m 0644 "$TIMER_FILE" "$SYSTEMD_DIR/ai-tools-update.timer"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
param([string]$ConfigRoot = (Join-Path $env:USERPROFILE '.agent-run'))
|
|
2
|
+
$ErrorActionPreference = 'Stop'
|
|
3
|
+
$ConfigRoot = [System.IO.Path]::GetFullPath($ConfigRoot)
|
|
4
|
+
$runner = Join-Path $PSScriptRoot 'run-windows-cleanup.ps1'
|
|
5
|
+
$launcher = Join-Path $PSScriptRoot 'run-hidden.vbs'
|
|
6
|
+
if ($ConfigRoot.Contains('"') -or $runner.Contains('"') -or $launcher.Contains('"')) { throw 'Paths cannot contain quotes.' }
|
|
7
|
+
$wscript = Join-Path $env:SystemRoot 'System32\wscript.exe'
|
|
8
|
+
$account = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
|
|
9
|
+
$action = New-ScheduledTaskAction -Execute $wscript -Argument "//B //NoLogo `"$launcher`" `"$runner`" -ConfigRoot `"$ConfigRoot`"" -WorkingDirectory $env:USERPROFILE
|
|
10
|
+
$principal = New-ScheduledTaskPrincipal -UserId $account -LogonType Interactive -RunLevel Limited
|
|
11
|
+
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(10) -RepetitionInterval (New-TimeSpan -Hours 1)
|
|
12
|
+
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit (New-TimeSpan -Minutes 30) -MultipleInstances IgnoreNew
|
|
13
|
+
Register-ScheduledTask -TaskName 'Agent Session Cleanup' -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description 'Hourly agent-run session retention cleanup for the signed-in user.' -Force | Out-Null
|
|
14
|
+
Write-Host "Agent Session Cleanup registered hourly for $account. Retention: $ConfigRoot\cleanup.env (default 7 days). Log: $ConfigRoot\runtime\cleanup.log"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
param([Parameter(Mandatory = $true)][string]$ConfigRoot)
|
|
2
|
+
$ErrorActionPreference = 'Stop'
|
|
3
|
+
$ConfigRoot = [System.IO.Path]::GetFullPath($ConfigRoot)
|
|
4
|
+
$env:Path = [Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' + [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
5
|
+
# Do not inherit a wrapper's guarded PATH or a particular interactive session.
|
|
6
|
+
foreach ($name in @('AGENT_RUN_REAL_PATH', 'CODEX_THREAD_ID', 'CODEX_SESSION_ID', 'CLAUDE_SESSION_ID', 'GROK_SESSION_ID')) {
|
|
7
|
+
[Environment]::SetEnvironmentVariable($name, $null, 'Process')
|
|
8
|
+
}
|
|
9
|
+
Set-Location $env:USERPROFILE
|
|
10
|
+
$runtime = Join-Path $ConfigRoot 'runtime'
|
|
11
|
+
New-Item -ItemType Directory -Path $runtime -Force | Out-Null
|
|
12
|
+
$log = Join-Path $runtime 'cleanup.log'
|
|
13
|
+
$agentRun = Join-Path $PSScriptRoot '..\dist\agent-run.js'
|
|
14
|
+
try {
|
|
15
|
+
$node = (Get-Command node.exe -ErrorAction Stop).Source
|
|
16
|
+
# Native stderr is diagnostic output; the native exit status decides failure.
|
|
17
|
+
$ErrorActionPreference = 'Continue'
|
|
18
|
+
& $node $agentRun --configdir $ConfigRoot --clean-old all *> $log
|
|
19
|
+
exit $LASTEXITCODE
|
|
20
|
+
} catch {
|
|
21
|
+
$_ | Out-File -FilePath $log
|
|
22
|
+
exit 1
|
|
23
|
+
}
|