chore: v2.8.12 — clone queue and progress, session defaults, chat agents, drops as @ mentions
Whole tree from parallel sessions, plus the version bump: - Clone: a queue with live progress (Add workspace and extra folders), clones run under nice/ionice so the machine stays responsive. - Settings → AI tools → Session defaults: a new session's default permission mode / bypass per account. - Chat lists the background subagents that have not reported back yet. - A file pasted or dropped into a claude pane goes in as an @ mention. - Changes panel: say why amend/undo is refused on a pushed commit. - openapi.yaml regenerated (Artifacts, Host, resumeById).
This commit is contained in:
@@ -777,6 +777,10 @@ async function cloneInto(req, res, body, before) {
|
||||
res.status(400).json({ error: { code: "EBADTOOL", message: "unknown tool" } });
|
||||
return null;
|
||||
}
|
||||
if (body.partial !== undefined && typeof body.partial !== "boolean") {
|
||||
res.status(400).json({ error: { code: "EBADFIELD", message: "partial: boolean" } });
|
||||
return null;
|
||||
}
|
||||
const once = body.credentials;
|
||||
if (once != null && (typeof once !== "object" || Array.isArray(once))) {
|
||||
res.status(400).json({ error: { code: "EBADCRED", message: "credentials: object" } });
|
||||
@@ -813,17 +817,32 @@ async function cloneInto(req, res, body, before) {
|
||||
return null;
|
||||
}
|
||||
const ownerId = scope.ownerFor(req);
|
||||
// The browser's own name for this clone, so it can poll its progress.
|
||||
const queue = require("../lib/clone-queue");
|
||||
let job = null;
|
||||
if (body.progressToken !== undefined) {
|
||||
try {
|
||||
job = queue.track(body.progressToken, ownerId);
|
||||
} catch (err) {
|
||||
res.status(400).json({ error: { code: err.code, message: err.message } });
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
await before(target, ownerId);
|
||||
await identity.cloneRepo({
|
||||
job,
|
||||
url,
|
||||
parent: dir,
|
||||
name,
|
||||
once: once
|
||||
? { username: once.username, password: once.password, remember: once.remember === true }
|
||||
: null,
|
||||
partial: body.partial === true,
|
||||
});
|
||||
queue.finish(job, true);
|
||||
} catch (err) {
|
||||
queue.finish(job, false);
|
||||
const status = ["EBADCRED", "EBADHOST", "EBADTOOL", "EDISABLED"].includes(err.code)
|
||||
? 400
|
||||
: ["ECREDENTIALS", "ESSHAUTH", "ENOREPO", "EOWNERFOLDER", "EMEMBERGONE"].includes(err.code)
|
||||
@@ -843,6 +862,19 @@ async function cloneInto(req, res, body, before) {
|
||||
return { target, name, ownerId };
|
||||
}
|
||||
|
||||
/**
|
||||
* A clone's place in the machine-wide queue, then git's own progress
|
||||
* (`server/lib/clone-queue.js`), by the `progressToken` its POST carried —
|
||||
* only to the user who started it (404 otherwise, and once it is long over).
|
||||
*/
|
||||
router.get("/clone/progress/:token", (req, res) => {
|
||||
const view = require("../lib/clone-queue").progress(req.params.token, scope.ownerFor(req));
|
||||
if (!view) {
|
||||
return res.status(404).json({ error: { code: "ENOTFOUND", message: "no such clone" } });
|
||||
}
|
||||
res.json(view);
|
||||
});
|
||||
|
||||
router.post("/clone", sameOriginGuard, async (req, res) => {
|
||||
const body = req.body || {};
|
||||
// Before the clone: a workspace this user may not own there, or a tool
|
||||
|
||||
Reference in New Issue
Block a user