feat(api): accept a lane tool on create, start and binary probe
This commit is contained in:
+20
-1
@@ -260,6 +260,11 @@ router.post("/ensure", sameOriginGuard, (req, res) => {
|
||||
// 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();
|
||||
|
||||
if (body.tool !== undefined && !lanesLib.VALID_TOOLS.has(body.tool)) {
|
||||
return res.status(400).json({ error: { code: "EBADTOOL", message: "unknown tool" } });
|
||||
}
|
||||
|
||||
const owner = lanesLib.resolveLaneByCwd(cwd);
|
||||
if (owner) {
|
||||
// First-write wins on the title: an ensure-with-title on an existing lane
|
||||
@@ -276,11 +281,12 @@ router.post("/ensure", sameOriginGuard, (req, res) => {
|
||||
cwd,
|
||||
title: body.title || "",
|
||||
...(body.pipeline ? { pipeline: body.pipeline } : {}),
|
||||
...(body.tool ? { tool: body.tool } : {}),
|
||||
});
|
||||
broadcastLane(lane.id);
|
||||
return res.status(201).json({ lane: payload(lane), created: true });
|
||||
} catch (err) {
|
||||
if (err.code === "EBADCWD" || err.code === "EBADPIPELINE") {
|
||||
if (err.code === "EBADCWD" || err.code === "EBADPIPELINE" || err.code === "EBADTOOL") {
|
||||
return res.status(400).json({ error: { code: err.code, message: err.message } });
|
||||
}
|
||||
// The cwd UNIQUE constraint is the arbiter: someone else won the race, so
|
||||
@@ -641,6 +647,11 @@ router.get("/:id/ci/status", async (req, res) => {
|
||||
*/
|
||||
router.post("/worktree", sameOriginGuard, async (req, res) => {
|
||||
const body = req.body || {};
|
||||
|
||||
if (body.tool !== undefined && !lanesLib.VALID_TOOLS.has(body.tool)) {
|
||||
return res.status(400).json({ error: { code: "EBADTOOL", message: "unknown tool" } });
|
||||
}
|
||||
|
||||
const sourceRepo = body.sourceRepo;
|
||||
if (
|
||||
typeof sourceRepo !== "string" ||
|
||||
@@ -706,6 +717,7 @@ router.post("/worktree", sameOriginGuard, async (req, res) => {
|
||||
base_branch: body.base || null,
|
||||
slug,
|
||||
...(body.pipeline ? { pipeline: body.pipeline } : {}),
|
||||
...(body.tool ? { tool: body.tool } : {}),
|
||||
});
|
||||
lane = lanesLib.updateLane(lane.id, { status: "provisioning" });
|
||||
} catch (err) {
|
||||
@@ -1230,9 +1242,16 @@ router.post("/:id/:action", sameOriginGuard, async (req, res) => {
|
||||
laneId: current.id,
|
||||
initialPrompt: body.prompt || "",
|
||||
cwd: current.cwd,
|
||||
// The tool is the LANE's fact, never the request's: a client that
|
||||
// asked for the other CLI would otherwise get a pane that doesn't
|
||||
// match the lane's badge, its history, or its binary probe.
|
||||
tool: current.tool || "claude",
|
||||
model: body.model,
|
||||
permissionMode: body.permissionMode,
|
||||
effort: body.effort,
|
||||
sandbox: body.sandbox,
|
||||
approval: body.approval,
|
||||
resumeLast: body.resumeLast === true,
|
||||
resumeSessionId: body.resumeSessionId || (body.resume ? current.session_id : undefined),
|
||||
});
|
||||
lanesLib.updateLane(current.id, { run_id: handle.id, status: "running" });
|
||||
|
||||
Reference in New Issue
Block a user