feat(sagi): spawn a real claude session for Sagi's Ask handoff
Unmatched Ask questions now adopt a dedicated "Sagi" lane (POST /api/lanes/ensure, cwd defaults to $HOME) and spawn a tmux-backed claude run there instead of just prefilling the Run page composer.
This commit is contained in:
+18
-4
@@ -161,11 +161,25 @@ router.get("/branches", async (req, res) => {
|
||||
*/
|
||||
router.post("/ensure", sameOriginGuard, (req, res) => {
|
||||
const body = req.body || {};
|
||||
const owner = lanesLib.resolveLaneByCwd(body.cwd);
|
||||
if (owner) return res.json({ lane: payload(owner), created: false });
|
||||
// Default the cwd to the user's home so callers that don't care about a
|
||||
// specific directory (e.g. Sagi's mascot companion) get a real, existing
|
||||
// path and lane uniqueness stays meaningful. Callers that do care pass one
|
||||
// through unchanged.
|
||||
const cwd = typeof body.cwd === "string" && body.cwd.trim() ? body.cwd.trim() : os.homedir();
|
||||
const owner = lanesLib.resolveLaneByCwd(cwd);
|
||||
if (owner) {
|
||||
// First-write wins on the title: an ensure-with-title on an existing lane
|
||||
// is how callers like Sagi adopt the lane, so don't clobber a real title
|
||||
// with an empty one.
|
||||
if (body.title && !owner.title) {
|
||||
const updated = lanesLib.updateLane(owner.id, { title: body.title });
|
||||
return res.json({ lane: payload(updated || owner), created: false });
|
||||
}
|
||||
return res.json({ lane: payload(owner), created: false });
|
||||
}
|
||||
try {
|
||||
const lane = lanesLib.createLane({
|
||||
cwd: body.cwd,
|
||||
cwd,
|
||||
title: body.title || "",
|
||||
...(body.pipeline ? { pipeline: body.pipeline } : {}),
|
||||
});
|
||||
@@ -178,7 +192,7 @@ router.post("/ensure", sameOriginGuard, (req, res) => {
|
||||
// The cwd UNIQUE constraint is the arbiter: someone else won the race, so
|
||||
// re-read and return THEIR lane rather than reporting a conflict.
|
||||
if (err.code === "SQLITE_CONSTRAINT_UNIQUE" || String(err.message).includes("UNIQUE")) {
|
||||
const winner = lanesLib.resolveLaneByCwd(body.cwd);
|
||||
const winner = lanesLib.resolveLaneByCwd(cwd);
|
||||
if (winner) return res.json({ lane: payload(winner), created: false });
|
||||
}
|
||||
return res.status(500).json({ error: { code: err.code, message: err.message } });
|
||||
|
||||
Reference in New Issue
Block a user