feat: per-change-block hunk actions (#50), codex lanes without a pipeline, macOS LaunchAgent
- git (#50): stage-hunk/discard-hunk take an optional `block` — one run of consecutive +/- lines inside an @@ hunk. `onlyBlock` (server/lib/git-diff.js) cuts git's fresh hunk down to it, folding the other blocks into the side being checked; LaneDiffView hangs one review bar per block (unified + split) and its arrows walk blocks. - git exclude: entries AgentHub writes for a lane go to the COMMON git dir with the lane's path prefix (server/lib/git-exclude.js, used by router-apply and lane-mcp) — a linked worktree's own info/exclude is never read by git, and a subdir lane has no .git. MCP sync no longer fails with ENOTDIR on a worktree lane or creates a stray .git in a non-repo lane. - codex lanes carry no pipeline: codex-ingest mirrors only idle/running, codex-nudge is removed, agents install writes nothing for codex, the Workspace hides stage/pipeline/feature pickers/PipelineMap for them, and every server start clears leftover codex stage data and the old AGENTS.md stage block. - Changes panel: a whole file opens for reading and enters the editor on a click on its text (caret at the clicked line), not automatically. - macOS: LaunchAgent start-at-login (scripts/launchd-service.js, picked by scripts/service-manager.js). - Adds the AgentHub introduction slides and their image-embedding script.
This commit is contained in:
+33
-18
@@ -1463,16 +1463,24 @@ async function cmdStart(flags) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs/removes a systemd `--user` service so the dashboard survives
|
||||
* reboots without anything (Claude Code included) needing to start it first.
|
||||
* Linux/systemd only; other platforms are told to keep using `agenthub start`.
|
||||
* Installs/removes a systemd `--user` service (Linux) or a LaunchAgent
|
||||
* (macOS) so the dashboard survives reboots without anything (Claude Code
|
||||
* included) needing to start it first. Elsewhere, `agenthub start` by hand.
|
||||
*/
|
||||
async function cmdService(sub, flags) {
|
||||
const svc = require(path.join(REPO_ROOT, "scripts", "systemd-service.js"));
|
||||
const svc = require(path.join(REPO_ROOT, "scripts", "service-manager.js"));
|
||||
if (!svc.systemctlAvailable()) {
|
||||
console.error(c.red("✖ systemd --user is not available on this machine."));
|
||||
console.error(
|
||||
c.dim(" Auto-start on boot needs Linux + systemd. Use `agenthub start` manually instead.")
|
||||
c.red(
|
||||
`✖ ${svc.kind === "launchd" ? "launchd (a GUI login session)" : "systemd --user"} is not available here.`
|
||||
)
|
||||
);
|
||||
console.error(
|
||||
c.dim(
|
||||
svc.kind === "launchd"
|
||||
? " A LaunchAgent needs the user logged in at the Mac itself, not only over SSH. Use `agenthub start` meanwhile."
|
||||
: " Auto-start on boot needs Linux + systemd. Use `agenthub start` manually instead."
|
||||
)
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -1493,24 +1501,27 @@ async function cmdService(sub, flags) {
|
||||
description: "AgentHub dashboard server",
|
||||
workingDir: REPO_ROOT,
|
||||
execStart: `${process.execPath} ${path.join(REPO_ROOT, "server", "index.js")}`,
|
||||
argv: [process.execPath, path.join(REPO_ROOT, "server", "index.js")],
|
||||
env,
|
||||
});
|
||||
if (result === "foreign") {
|
||||
console.error(
|
||||
c.red(
|
||||
`✖ ~/.config/systemd/user/${name}.service already exists and wasn't written by agenthub.`
|
||||
)
|
||||
c.red(`✖ ${svc.unitPath(name)} already exists and wasn't written by agenthub.`)
|
||||
);
|
||||
console.error(c.dim(" Remove or rename it, then re-run `agenthub service install`."));
|
||||
process.exit(1);
|
||||
}
|
||||
if (result === "failed") {
|
||||
console.error(c.red("✖ Failed to write/enable the systemd unit."));
|
||||
console.error(c.red(`✖ Failed to write/enable the ${svc.label}.`));
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(
|
||||
`${c.green("✔")} systemd --user service '${name}' ${result === "unchanged" ? "already up to date" : "installed"} and enabled.`
|
||||
`${c.green("✔")} ${svc.label} '${name}' ${result === "unchanged" ? "already up to date" : "installed"} and enabled.`
|
||||
);
|
||||
if (svc.kind === "launchd") {
|
||||
console.log(c.dim(` It starts at every login. Server log: ${svc.logPath()}`));
|
||||
return;
|
||||
}
|
||||
const lingered = svc.enableLinger();
|
||||
if (lingered) {
|
||||
console.log(
|
||||
@@ -1531,20 +1542,24 @@ async function cmdService(sub, flags) {
|
||||
if (sub === "uninstall") {
|
||||
const result = svc.uninstallUserService(name);
|
||||
if (result === "foreign") {
|
||||
console.error(
|
||||
c.red(
|
||||
`✖ ~/.config/systemd/user/${name}.service wasn't written by agenthub — not touching it.`
|
||||
)
|
||||
);
|
||||
console.error(c.red(`✖ ${svc.unitPath(name)} wasn't written by agenthub — not touching it.`));
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(
|
||||
`${c.green("✔")} systemd service ${result === "absent" ? "was not installed" : "removed"}.`
|
||||
`${c.green("✔")} ${svc.label} ${result === "absent" ? "was not installed" : "removed"}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (sub === "status") {
|
||||
spawn("systemctl", ["--user", "status", `${name}.service`, "--no-pager"], { stdio: "inherit" });
|
||||
if (svc.kind === "launchd") {
|
||||
spawn("launchctl", ["print", `gui/${process.getuid()}/io.smartgift.${name}`], {
|
||||
stdio: "inherit",
|
||||
});
|
||||
} else {
|
||||
spawn("systemctl", ["--user", "status", `${name}.service`, "--no-pager"], {
|
||||
stdio: "inherit",
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
console.error(c.red("✖ Usage: agenthub service install|uninstall|status [--port N]"));
|
||||
|
||||
Reference in New Issue
Block a user