@a-t-h-i/bot-lobby 0.6.33 → 0.6.34
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/README.md +30 -0
- package/package.json +7 -7
- package/src/desk/client-extension.ts +2 -2
- package/src/desk/ipc.ts +4 -3
- package/src/desk/session.ts +14 -1
- package/src/execution/agent-runner.ts +16 -92
- package/src/execution/delegation.ts +193 -0
- package/src/execution/live-run.ts +95 -0
- package/src/execution/pi-runner.ts +35 -9
- package/src/index.ts +5 -0
- package/src/lobby/planner.ts +9 -0
- package/src/lobby/pr-review.ts +9 -0
- package/src/lobby/quickfix.ts +16 -0
- package/src/master/master.ts +3 -1
- package/src/master/research.ts +1 -0
- package/src/pi/auto-compaction.ts +72 -0
- package/src/pi/delegation.ts +68 -0
- package/src/pi/model-support.ts +1 -1
- package/src/pi/plan-checklist.ts +18 -7
- package/src/pi/run-summary.ts +9 -0
- package/src/schemas/configuration.ts +19 -7
- package/src/schemas/findings.ts +4 -0
- package/src/schemas/task.ts +4 -0
- package/src/state/work-time.ts +4 -2
- package/src/webui/api/lobby.ts +1 -1
- package/src/webui/api/plan-facts.ts +4 -3
- package/src/webui/api/tasks.ts +1 -1
- package/src/webui/dev/fake-service.ts +1 -1
- package/src/webui/dev/fixtures.ts +1 -1
- package/src/webui/protocol.ts +2 -2
- package/src/workflow/workflow.ts +4 -1
- package/webui/dist/assets/{index-BFra71Rf.js → index-B4zpEv7K.js} +5 -4
- package/webui/dist/assets/index-C8hgfw6m.css +2 -0
- package/webui/dist/build.json +13 -13
- package/webui/dist/index.html +2 -2
- package/webui/dist/assets/index-D5_tWSK0.css +0 -2
package/src/schemas/task.ts
CHANGED
|
@@ -77,6 +77,10 @@ export const MAX_WORKER_RECORDS = 64;
|
|
|
77
77
|
/** One finished subagent run of any role, kept for `/bot-lobby runs`. */
|
|
78
78
|
export interface RunLogEntry {
|
|
79
79
|
runId: string;
|
|
80
|
+
parentRunId?: string;
|
|
81
|
+
depth?: number;
|
|
82
|
+
instruction?: string;
|
|
83
|
+
stepInstruction?: string;
|
|
80
84
|
domain: Domain;
|
|
81
85
|
role: Role;
|
|
82
86
|
status: "running" | "success" | "failed" | "cancelled" | "timeout";
|
package/src/state/work-time.ts
CHANGED
|
@@ -15,6 +15,8 @@ import { taskDirFor } from "./persistence.ts";
|
|
|
15
15
|
/** A worker run under way: the step it works on is found from its instruction. */
|
|
16
16
|
export interface ActiveRun {
|
|
17
17
|
runId: string;
|
|
18
|
+
parentRunId?: string;
|
|
19
|
+
stepInstruction?: string;
|
|
18
20
|
instruction: string;
|
|
19
21
|
startedAt: string;
|
|
20
22
|
}
|
|
@@ -97,7 +99,7 @@ export function taskWork(root: string, configDir: string, taskId: string, now =
|
|
|
97
99
|
const noted = new Map<string, Set<string>>();
|
|
98
100
|
|
|
99
101
|
/** A worker run of the task started or ended: the steps it works on read as active while it runs. */
|
|
100
|
-
export function noteWorkerRun(root: string, configDir: string, taskId: string, run: { runId: string; instruction?: string; startedAt: string; status: string }): void {
|
|
102
|
+
export function noteWorkerRun(root: string, configDir: string, taskId: string, run: { runId: string; parentRunId?: string; stepInstruction?: string; instruction?: string; startedAt: string; status: string }): void {
|
|
101
103
|
const running = run.status === "running";
|
|
102
104
|
const ids = noted.get(taskId) ?? new Set<string>();
|
|
103
105
|
if (running === ids.has(run.runId)) return;
|
|
@@ -106,7 +108,7 @@ export function noteWorkerRun(root: string, configDir: string, taskId: string, r
|
|
|
106
108
|
noted.set(taskId, ids);
|
|
107
109
|
updateWork(root, configDir, taskId, (work) => {
|
|
108
110
|
work.active = work.active.filter((entry) => entry.runId !== run.runId);
|
|
109
|
-
if (running) work.active.push({ runId: run.runId, instruction: run.instruction ?? "", startedAt: run.startedAt });
|
|
111
|
+
if (running) work.active.push({ runId: run.runId, instruction: run.instruction ?? "", startedAt: run.startedAt, ...(run.parentRunId ? { parentRunId: run.parentRunId } : {}), ...(run.stepInstruction ? { stepInstruction: run.stepInstruction } : {}) });
|
|
110
112
|
});
|
|
111
113
|
}
|
|
112
114
|
|
package/src/webui/api/lobby.ts
CHANGED
|
@@ -24,7 +24,7 @@ function planFacts(task: Task, work: WorkProjection | undefined): Pick<SnapshotT
|
|
|
24
24
|
return {
|
|
25
25
|
progress: { done: steps.filter((step) => step.status === "done").length, total: steps.length },
|
|
26
26
|
...(current ? { currentStep: current.text } : {}),
|
|
27
|
-
...(active.length > 0 ? { activeSteps: active.map((step) => ({ text: step.text, workedMs: step.workedMs })) } : {}),
|
|
27
|
+
...(active.length > 0 ? { activeSteps: active.map((step) => ({ text: step.text, workedMs: step.workedMs, activeAgentCount: step.activeAgentCount })) } : {}),
|
|
28
28
|
...clock,
|
|
29
29
|
};
|
|
30
30
|
}
|
|
@@ -30,7 +30,7 @@ function activeRuns(task: Task, work: WorkProjection | undefined): AgentRun[] {
|
|
|
30
30
|
const finished = new Set((task.workerRuns ?? []).map((record) => record.runId));
|
|
31
31
|
return (work?.active ?? [])
|
|
32
32
|
.filter((run) => !finished.has(run.runId))
|
|
33
|
-
.map((run) => ({ runId: run.runId, taskId: task.id, domain: "backend" as const, role: "worker" as const, status: "running" as const, instruction: run.instruction, output: "", attempts: 1, startedAt: run.startedAt }));
|
|
33
|
+
.map((run) => ({ runId: run.runId, parentRunId: run.parentRunId, stepInstruction: run.stepInstruction, taskId: task.id, domain: "backend" as const, role: "worker" as const, status: "running" as const, instruction: run.instruction, output: "", attempts: 1, startedAt: run.startedAt }));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/** One step as the lobby shows it: its state, and while a worker is on it, how long they have worked on it. */
|
|
@@ -38,6 +38,7 @@ export interface StepView {
|
|
|
38
38
|
text: string;
|
|
39
39
|
status: PlanStep["status"];
|
|
40
40
|
active: boolean;
|
|
41
|
+
activeAgentCount: number;
|
|
41
42
|
/** Worker time on the step, in ms. */
|
|
42
43
|
workedMs: number;
|
|
43
44
|
}
|
|
@@ -53,7 +54,7 @@ export function stepViews(task: Task, work: WorkProjection | undefined, now = Da
|
|
|
53
54
|
const checklist = planChecklist(task.plan, runs);
|
|
54
55
|
const times = stepWork(planSteps(task.plan), runs, now);
|
|
55
56
|
return checklist.map((step, index) => {
|
|
56
|
-
const time = times[index] ?? { ms: 0, active: false };
|
|
57
|
-
return { text: step.text, status: time.active ? "current" : step.status, active: time.active, workedMs: Math.round(time.ms) };
|
|
57
|
+
const time = times[index] ?? { ms: 0, active: false, activeAgentCount: 0 };
|
|
58
|
+
return { text: step.text, status: time.active ? "current" : step.status, active: time.active, activeAgentCount: time.activeAgentCount, workedMs: Math.round(time.ms) };
|
|
58
59
|
});
|
|
59
60
|
}
|
package/src/webui/api/tasks.ts
CHANGED
|
@@ -311,7 +311,7 @@ export function tasksGet(body: { taskId: string }, ctx: ApiContext): TaskDetail
|
|
|
311
311
|
steps: stepViews(found, work, now).map((step) => ({
|
|
312
312
|
text: step.text,
|
|
313
313
|
status: step.status === "pending" ? "open" : step.status,
|
|
314
|
-
...(step.active ? { active: true, workedMs: step.workedMs } : {}),
|
|
314
|
+
...(step.active ? { active: true, workedMs: step.workedMs, activeAgentCount: step.activeAgentCount } : {}),
|
|
315
315
|
})),
|
|
316
316
|
amendments: [...found.amendments],
|
|
317
317
|
waiting: waitingOf(found),
|
|
@@ -478,7 +478,7 @@ export function createFixtureService(name: string, feed = new LobbyFeed()): Lobb
|
|
|
478
478
|
const work = fixture.mockWork?.[taskId];
|
|
479
479
|
if (!work) return undefined;
|
|
480
480
|
const now = Date.now();
|
|
481
|
-
return { workedMs: work.workedMs, running: work.running, active: (work.active ?? []).map((run) => ({ runId: run.runId, instruction: run.instruction, startedAt: new Date(now - run.startedAgoMs).toISOString() })) };
|
|
481
|
+
return { workedMs: work.workedMs, running: work.running, active: (work.active ?? []).map((run) => ({ runId: run.runId, parentRunId: run.parentRunId, stepInstruction: run.stepInstruction, instruction: run.instruction, startedAt: new Date(now - run.startedAgoMs).toISOString() })) };
|
|
482
482
|
},
|
|
483
483
|
plans: () => [...plans],
|
|
484
484
|
metrics: () => metrics.map((record) => ({ ...record })),
|
|
@@ -65,7 +65,7 @@ export interface ScenarioFixture {
|
|
|
65
65
|
/** Tasks backing `tasks.list` (absent means none). */
|
|
66
66
|
mockTasks?: Array<Record<string, unknown>>;
|
|
67
67
|
/** Work clocks by task id (`work.json` as the owner keeps it); a run's start is given as how long ago, so it reads live. */
|
|
68
|
-
mockWork?: Record<string, { workedMs: number; running: boolean; active?: Array<{ runId: string; instruction: string; startedAgoMs: number }> }>;
|
|
68
|
+
mockWork?: Record<string, { workedMs: number; running: boolean; active?: Array<{ runId: string; parentRunId?: string; stepInstruction?: string; instruction: string; startedAgoMs: number }> }>;
|
|
69
69
|
/** Saved plans backing `plans.start`/`plans.discard` and the pending rows. */
|
|
70
70
|
mockPlans?: Array<{ id: string; title: string; brief: string }>;
|
|
71
71
|
/** Archived tasks backing `tasks.archived`. */
|
package/src/webui/protocol.ts
CHANGED
|
@@ -131,7 +131,7 @@ export interface SnapshotTask {
|
|
|
131
131
|
progress?: { done: number; total: number };
|
|
132
132
|
currentStep?: string;
|
|
133
133
|
/** The steps a worker is on right now, with the worker time on each (ms, as of the snapshot). */
|
|
134
|
-
activeSteps?: Array<{ text: string; workedMs: number }>;
|
|
134
|
+
activeSteps?: Array<{ text: string; workedMs: number; activeAgentCount?: number }>;
|
|
135
135
|
/** How long the task's agents have worked on it, idle time left out. */
|
|
136
136
|
work?: WorkClock;
|
|
137
137
|
}
|
|
@@ -420,7 +420,7 @@ export interface TaskDetail {
|
|
|
420
420
|
* The plan as a checklist, in order; `current` is the step under way, `active` the steps a worker is on right now,
|
|
421
421
|
* each with its worker time (ms, as of the reply).
|
|
422
422
|
*/
|
|
423
|
-
steps: Array<{ text: string; status: "done" | "current" | "open"; active?: boolean; workedMs?: number }>;
|
|
423
|
+
steps: Array<{ text: string; status: "done" | "current" | "open"; active?: boolean; workedMs?: number; activeAgentCount?: number }>;
|
|
424
424
|
/** How long the task's agents have worked on it, idle time left out (ms, as of the reply); `running` while they work. */
|
|
425
425
|
work?: WorkClock;
|
|
426
426
|
amendments: string[];
|
package/src/workflow/workflow.ts
CHANGED
|
@@ -2012,7 +2012,10 @@ export async function runWorkflowAction(params: OrchestrateParams, deps: Workflo
|
|
|
2012
2012
|
// Every agent, diff and desk of a task with its own worktree works there.
|
|
2013
2013
|
cwd: taskCwd(task, deps.cwd),
|
|
2014
2014
|
onUpdate: (run) => {
|
|
2015
|
-
if (run.status !== "running")
|
|
2015
|
+
if (run.status !== "running") {
|
|
2016
|
+
finished.set(run.runId, run);
|
|
2017
|
+
if (run.parentRunId) writeFileEnsured(join(taskDirFor(deps.root, deps.configDir, task.id), "children", `${run.runId}.json`), `${JSON.stringify(run)}\n`);
|
|
2018
|
+
}
|
|
2016
2019
|
// Every window marks the steps a worker is on while it runs.
|
|
2017
2020
|
if (run.role === "worker") {
|
|
2018
2021
|
if (run.status === "running") working.add(run.runId);
|