feat(ui): a Claude-Desktop-style home for every workspace
/workspace?lane=<id> opens on the workspace's home (WorkspaceHome): a prompt box whose Start opens a new session in the first free pane slot, Recents (a live session attaches its pane, any other opens its transcript, nothing resumes), and Instructions / Memory / Context / Folder. Instructions live in lanes.instructions, extra folders and uploaded files in the new lane_sources table (copies under <data dir>/workspace-context/<lane id>/); spawnRun reads them from the lane's rows and hands Claude --add-dir + an appended system prompt file, Codex --add-dir + developer_instructions. Memory is read-only. Every dashboard pane carries AGENTHUB_RUN_ID; hooks forward it and the run records which session the pane holds (a Claude pane follows /clear and /resume but not a nested claude -p), so the sidebar and notifications open the right pane (&run=). Settings loses its Projects group; Worktrees now decides which worktrees Add folder suggests.
This commit is contained in:
+19
-2
@@ -357,7 +357,20 @@ function setProvisioningFacts(id, facts = {}) {
|
||||
}
|
||||
|
||||
function deleteLane(id) {
|
||||
return db.prepare("DELETE FROM lanes WHERE id = ?").run(id).changes > 0;
|
||||
const gone = db.prepare("DELETE FROM lanes WHERE id = ?").run(id).changes > 0;
|
||||
// Its `lane_sources` rows cascade; AgentHub's own copies of its uploaded
|
||||
// context files go with them. A folder source is the user's and stays.
|
||||
// Lazy: lane-sources.js reads the db directly and must not load at import.
|
||||
// The row is already gone: a copy that will not delete is logged, not a
|
||||
// failed remove.
|
||||
if (gone) {
|
||||
try {
|
||||
require("./lane-sources").removeLaneContext(id);
|
||||
} catch (err) {
|
||||
console.warn(`[lanes] workspace ${id}: context files not removed:`, err.message);
|
||||
}
|
||||
}
|
||||
return gone;
|
||||
}
|
||||
|
||||
/** Slots currently held by a lane, ascending. Input to the slot allocator. */
|
||||
@@ -755,8 +768,12 @@ function lanePayload(lane, ageSec = null) {
|
||||
const inferredIdx = inferred ? phaseIdx(pipeline, inferred) : -1;
|
||||
const view = inferredIdx === -1 ? lane : { ...lane, stage: inferred };
|
||||
const nodes = nodeStates(pipeline, view);
|
||||
// Up to 16 KB per lane, on every list and broadcast; the home reads it from
|
||||
// `GET /api/lanes/:id/sources` instead.
|
||||
const row = { ...lane };
|
||||
delete row.instructions;
|
||||
return {
|
||||
...lane,
|
||||
...row,
|
||||
pipeline_name: pipeline.name,
|
||||
pipeline_skill: pipeline.skill || "",
|
||||
pipeline_nodes:
|
||||
|
||||
Reference in New Issue
Block a user