@galda/cli 0.10.56 → 0.10.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/app/index.html CHANGED
@@ -10054,6 +10054,12 @@ $('appmenu').addEventListener('click', (e) => {
10054
10054
  renderEffortSelect();
10055
10055
  renderMsgHint();
10056
10056
  $('appmenu').classList.remove('show');
10057
+ const projectId = state.active;
10058
+ if (projectId) fetch(withKey(`/api/projects/${encodeURIComponent(projectId)}/queue-agent`), {
10059
+ method: 'POST', headers: { 'content-type': 'application/json' },
10060
+ body: JSON.stringify({ agent: state.connectedApp, model: state.stickyModel, effort: state.stickyEffort }),
10061
+ }).then(async (r) => { if (!r.ok) showErr((await r.json().catch(() => ({}))).error || 'Could not update Next up.'); else await refresh(); })
10062
+ .catch(() => showErr('Could not update Next up.'));
10057
10063
  });
10058
10064
  document.addEventListener('click', (e) => {
10059
10065
  if (!e.target.closest('.appsel')) $('appmenu').classList.remove('show');
package/engine/server.mjs CHANGED
@@ -4008,6 +4008,40 @@ const server = createServer(async (req, res) => {
4008
4008
  return json(res, 200, task);
4009
4009
  }
4010
4010
 
4011
+ // The composer agent picker also owns Next up for this project. Only work
4012
+ // that has not started moves; running/review/done work keeps its original
4013
+ // agent and conversation.
4014
+ const queueAgentMatch = url.pathname.match(/^\/api\/projects\/([^/]+)\/queue-agent$/);
4015
+ if (queueAgentMatch && req.method === 'POST') {
4016
+ const projectId = decodeURIComponent(queueAgentMatch[1]);
4017
+ if (!projects.some((project) => project.id === projectId)) return json(res, 404, { error: 'project not found' });
4018
+ let body = '';
4019
+ req.on('data', (chunk) => { body += chunk; });
4020
+ req.on('end', () => {
4021
+ let requested;
4022
+ try { requested = JSON.parse(body || '{}'); } catch { return json(res, 400, { error: 'bad json' }); }
4023
+ if (!['claude-code', 'codex'].includes(requested.agent)) return json(res, 400, { error: 'unsupported agent' });
4024
+ const agent = workerAgent(requested.agent);
4025
+ if (!AVAILABLE_AGENTS.includes(agent)) return json(res, 409, { error: `${agent} is not connected on this device` });
4026
+ const model = workerModel(agent, requested.model);
4027
+ const effort = workerEffort(agent, requested.effort);
4028
+ const runningGoalIds = new Set(tasks.filter((task) => task.projectId === projectId && task.status === 'running').map((task) => task.goalId));
4029
+ const queued = tasks.filter((task) => task.projectId === projectId && task.status === 'queued' && !runningGoalIds.has(task.goalId));
4030
+ const goalIds = new Set(queued.map((task) => task.goalId));
4031
+ for (const task of queued) {
4032
+ task.agent = agent; task.model = model; task.effort = effort; task.sessionId = null;
4033
+ saveTask(task);
4034
+ }
4035
+ for (const goal of goals.filter((item) => goalIds.has(item.id))) {
4036
+ goal.agent = agent; goal.model = model; goal.effort = effort; goal.sessionId = null; goal.startedAt = null;
4037
+ saveGoal(goal);
4038
+ }
4039
+ pump(projectId);
4040
+ return json(res, 200, { changed: queued.length, agent, model, effort });
4041
+ });
4042
+ return;
4043
+ }
4044
+
4011
4045
  // A Claude usage hold should be actionable without asking people to edit
4012
4046
  // models or sessions. Move every still-queued step for this goal together so
4013
4047
  // one tap cannot leave a mixed Claude/Codex chain behind.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galda/cli",
3
- "version": "0.10.56",
3
+ "version": "0.10.57",
4
4
  "type": "module",
5
5
  "description": "Galda - hand off work to Claude Code or Codex, get proof back. Runs on your existing subscription, no extra API cost.",
6
6
  "scripts": {