Skip to content
Closed
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 packages/coding-agent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [Unreleased]

- Added `doctor` reporting of stray IPython kernels and stale kernel temp dirs; `doctor --fix` kills the orphaned kernels and removes the stale dirs, and `doctor --json` gains a `kernels` section.
- Fixed large IPython variables repeatedly slowing later turns by excluding them from persistent snapshots and removing them when context is compacted.
- Fixed daemon socket paths being used verbatim in identity derivations: on supported platforms, `--daemon-socket` spellings differing only by duplicate or trailing slashes now normalize to one canonical path, so worker-descriptor namespaces, daemon log files, and persisted descriptors agree.
- Added a `thinking` option to `rlm.run` for spawning subagents with an explicit reasoning level; invalid levels for the resolved child model fail spawn.
Expand Down
5 changes: 4 additions & 1 deletion packages/coding-agent/src/cli/command-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ export const COMMAND_SPECS: readonly CommandSpec[] = [
path: ["doctor"],
usage: "doctor [--fix] [--json]",
summary: "Inspect and safely clean up background services",
options: ["--fix Remove stale sockets and stop idle orphaned services", "--json Print JSON"],
options: [
"--fix Remove stale sockets, stop idle orphaned services, kill stray IPython kernels, and remove stale kernel temp dirs",
"--json Print JSON",
],
},
{
path: ["shutdown"],
Expand Down
29 changes: 22 additions & 7 deletions packages/coding-agent/src/cli/daemon-ps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ import type { DaemonWorkerDescriptor } from "../modes/daemon/daemon-worker-proto
import { signalProcessGroupOrProcess } from "../utils/child-process.js";
import { formatDaemonListTable } from "./daemon-ps-format.js";
import { promptYesNo } from "./daemon-stop-confirm.js";
import {
formatKernelFixResult,
formatKernelReport,
type KernelFindings,
type KernelFixResult,
kernelJsonSummary,
} from "./doctor-kernel-reap.js";

/**
* `daemon ps` discovers every prime-agent daemon on the machine, not just the
Expand Down Expand Up @@ -396,17 +403,21 @@ export function sortDaemons(infos: DaemonInfo[]): DaemonInfo[] {
});
}

export async function runPs(json: boolean): Promise<void> {
export async function runPs(json: boolean, kernels?: KernelFindings): Promise<void> {
const daemons = await discoverDaemons();
if (json) {
console.log(JSON.stringify(daemons, null, 2));
console.log(JSON.stringify(kernels ? { daemons, kernels: kernelJsonSummary(kernels) } : daemons, null, 2));
return;
}
if (daemons.length === 0) {
console.log("No background services found.");
return;
} else {
console.log(formatDaemonListTable(daemons));
}
const kernelReport = kernels ? formatKernelReport(kernels) : undefined;
if (kernelReport) {
console.log(kernelReport);
}
console.log(formatDaemonListTable(daemons));
}

export type ReapAction =
Expand Down Expand Up @@ -1067,7 +1078,7 @@ async function stopTrackedProcess(
return !isProcessAlive(pid);
}

export async function runReap(json: boolean, force: boolean): Promise<void> {
export async function runReap(json: boolean, force: boolean, kernelFix?: KernelFixResult): Promise<void> {
const daemons = await discoverDaemons();
const reaped: Array<{ socketPath: string; action: string }> = [];
const skipped: Array<{ socketPath: string; reason: string }> = [];
Expand Down Expand Up @@ -1113,10 +1124,11 @@ export async function runReap(json: boolean, force: boolean): Promise<void> {
}

if (json) {
console.log(JSON.stringify({ reaped, skipped }, null, 2));
console.log(JSON.stringify(kernelFix ? { reaped, skipped, kernels: kernelFix } : { reaped, skipped }, null, 2));
return;
}
if (reaped.length === 0 && skipped.length === 0) {
const kernelReport = kernelFix ? formatKernelFixResult(kernelFix) : undefined;
if (reaped.length === 0 && skipped.length === 0 && kernelReport === undefined) {
console.log("No background services found.");
return;
}
Expand All @@ -1126,6 +1138,9 @@ export async function runReap(json: boolean, force: boolean): Promise<void> {
for (const entry of skipped) {
console.log(chalk.dim(`kept ${entry.socketPath}: ${entry.reason}`));
}
if (kernelReport) {
console.log(kernelReport);
}
}

type ReapOutcome = { reaped: string } | { skipped: string };
Expand Down
Loading
Loading