@a-t-h-i/bot-lobby 0.6.0 → 0.6.2
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 +177 -799
- package/package.json +1 -1
- package/prompts/master.md +17 -0
- package/prompts/panel.md +3 -1
- package/prompts/planner.md +14 -0
- package/prompts/quickfix.md +3 -1
- package/prompts/scout.md +3 -0
- package/prompts/worker.md +3 -0
- package/src/classifier/answers.ts +110 -0
- package/src/classifier/classifier.ts +171 -0
- package/src/classifier/client.ts +239 -0
- package/src/classifier/effort.ts +143 -0
- package/src/classifier/files.ts +427 -0
- package/src/classifier/hosts.ts +157 -0
- package/src/classifier/instance.ts +98 -0
- package/src/classifier/limits.ts +37 -0
- package/src/classifier/seats.ts +102 -0
- package/src/classifier/tools.ts +58 -0
- package/src/classifier/triage.ts +203 -0
- package/src/execution/agent-runner.ts +5 -0
- package/src/index.ts +6 -0
- package/src/lobby/keys.ts +1 -1
- package/src/lobby/planner.ts +305 -27
- package/src/lobby/quickfix.ts +120 -8
- package/src/lobby/runtime.ts +136 -5
- package/src/lobby/session-files.ts +12 -0
- package/src/lobby/sessions.ts +28 -2
- package/src/lobby/tabs/home.ts +54 -26
- package/src/lobby/tabs/metrics.ts +28 -1
- package/src/lobby/tabs/plan.ts +27 -4
- package/src/lobby/tabs/quickfix.ts +5 -1
- package/src/lobby/tabs/tasks.ts +30 -14
- package/src/lobby/view.ts +334 -41
- package/src/master/master.ts +95 -29
- package/src/pi/commands.ts +24 -4
- package/src/pi/events.ts +11 -2
- package/src/pi/owner.ts +57 -8
- package/src/pi/run-summary.ts +3 -1
- package/src/pi/settings-ui.ts +138 -2
- package/src/pi/start-task.ts +4 -0
- package/src/pi/tools.ts +7 -2
- package/src/schemas/configuration.ts +125 -1
- package/src/schemas/findings.ts +4 -0
- package/src/schemas/task.ts +24 -0
- package/src/state/archive.ts +99 -0
- package/src/state/inbox.ts +49 -15
- package/src/state/metrics.ts +74 -1
- package/src/state/presence.ts +99 -0
- package/src/workflow/workflow.ts +49 -1
package/src/workflow/workflow.ts
CHANGED
|
@@ -47,6 +47,10 @@ import { assertNoPendingApprovals, pendingApprovals, requestApproval, resolveApp
|
|
|
47
47
|
import { pingApproval } from "../pi/notify.ts";
|
|
48
48
|
import { describeRun, runLogEntry } from "../pi/run-summary.ts";
|
|
49
49
|
import { nextStates } from "./transitions.ts";
|
|
50
|
+
import type { FileHinter } from "../classifier/files.ts";
|
|
51
|
+
import type { Classifier } from "../classifier/classifier.ts";
|
|
52
|
+
import type { EffortRouter } from "../classifier/effort.ts";
|
|
53
|
+
import { answerClarify } from "../classifier/triage.ts";
|
|
50
54
|
import { appendMetrics, metricFromRun } from "../state/metrics.ts";
|
|
51
55
|
import { markCommentsAddressed, pendingComments, readPlanComments } from "../state/comments.ts";
|
|
52
56
|
|
|
@@ -116,6 +120,14 @@ export interface WorkflowDeps {
|
|
|
116
120
|
choose: (title: string, options: string[]) => Promise<string | undefined>;
|
|
117
121
|
notify: (message: string, level?: "info" | "warning" | "error") => void;
|
|
118
122
|
runProcess?: ProcessRunner;
|
|
123
|
+
/** Likely files for scouts and workers, while the classifier's file hints are on. */
|
|
124
|
+
hints?: FileHinter;
|
|
125
|
+
/** Answers a clarify question whose recommended option is clearly right, when it is on. */
|
|
126
|
+
classifier?: Classifier;
|
|
127
|
+
/** Re-reads a request after an amendment (the task's triage), when the classifier is on. */
|
|
128
|
+
triage?: (request: string, signal?: AbortSignal) => Promise<Task["triage"]>;
|
|
129
|
+
/** Lowers thinking or the model for scouts and workers on steps the classifier judges simple or trivial. */
|
|
130
|
+
effort?: EffortRouter;
|
|
119
131
|
}
|
|
120
132
|
|
|
121
133
|
export interface WorkflowResult {
|
|
@@ -253,6 +265,11 @@ async function handleClarify(task: Task, params: OrchestrateParams, deps: Workfl
|
|
|
253
265
|
const question = params.question?.trim();
|
|
254
266
|
if (!question) throw new Error("clarify requires a question");
|
|
255
267
|
transition(task, "clarifying");
|
|
268
|
+
const settled = await clarifyByClassifier(task, question, params.options ?? [], deps);
|
|
269
|
+
if (settled) {
|
|
270
|
+
recordDecision(task, `Answered by the classifier (${settled.probability.toFixed(2)}): ${truncate(question, 300)} → ${settled.answer}`);
|
|
271
|
+
return `Answered by the classifier with your recommended option (${settled.probability.toFixed(2)}): ${settled.answer}. It is recorded as a decision; mention it in your proposal so the user can amend it, and continue.`;
|
|
272
|
+
}
|
|
256
273
|
const unattended = unattendedReason(task, isAutoMode(deps.root, deps.configDir, task.id));
|
|
257
274
|
if (unattended) {
|
|
258
275
|
recordDecision(task, `Not asked (${unattended}): ${truncate(question, 300)}`);
|
|
@@ -265,6 +282,20 @@ async function handleClarify(task: Task, params: OrchestrateParams, deps: Workfl
|
|
|
265
282
|
return `User answered: ${answer}`;
|
|
266
283
|
}
|
|
267
284
|
|
|
285
|
+
/** The classifier's answer to a clarify question with options, when the request already settles it. */
|
|
286
|
+
async function clarifyByClassifier(task: Task, question: string, options: readonly string[], deps: WorkflowDeps): Promise<{ answer: string; probability: number } | undefined> {
|
|
287
|
+
if (!deps.classifier || options.length < 2) return undefined;
|
|
288
|
+
const notes = [
|
|
289
|
+
...task.amendments.map((text) => `Amendment: ${text}`),
|
|
290
|
+
...task.decisions.slice(-12).map((decision) => `Decision: ${decision.text}`),
|
|
291
|
+
].join("\n");
|
|
292
|
+
try {
|
|
293
|
+
return await answerClarify(deps.classifier, question, options, { request: taskRequest(task), notes, ...(task.proposal ? { proposal: task.proposal } : {}) }, deps.signal);
|
|
294
|
+
} catch {
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
268
299
|
async function handleScout(task: Task, params: OrchestrateParams, deps: WorkflowDeps): Promise<string> {
|
|
269
300
|
requireState(task, ["created", "clarifying", "scouting", "synthesizing"]);
|
|
270
301
|
const domains = deriveDomains(params.domains);
|
|
@@ -284,6 +315,8 @@ async function handleScout(task: Task, params: OrchestrateParams, deps: Workflow
|
|
|
284
315
|
profile: deps.profile,
|
|
285
316
|
signal: deps.signal,
|
|
286
317
|
onUpdate: deps.onUpdate,
|
|
318
|
+
...(deps.hints ? { hints: deps.hints } : {}),
|
|
319
|
+
...(deps.effort ? { effort: deps.effort } : {}),
|
|
287
320
|
},
|
|
288
321
|
deps.runProcess ?? spawnPiProcess,
|
|
289
322
|
);
|
|
@@ -421,7 +454,20 @@ async function handlePropose(task: Task, params: OrchestrateParams, deps: Workfl
|
|
|
421
454
|
const lower = choice.toLowerCase();
|
|
422
455
|
if (lower.startsWith("approve")) return applyApprovalChoice(task, "approve");
|
|
423
456
|
if (lower.startsWith("decline")) return applyApprovalChoice(task, "decline");
|
|
424
|
-
|
|
457
|
+
const result = applyApprovalChoice(task, "amend", await deps.ask("What should change?"));
|
|
458
|
+
await retriage(task, deps);
|
|
459
|
+
return result;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/** After an amendment, the classifier reads the request again, so the Master's hints follow the change. */
|
|
463
|
+
async function retriage(task: Task, deps: WorkflowDeps): Promise<void> {
|
|
464
|
+
if (!deps.triage || !task.triage) return;
|
|
465
|
+
try {
|
|
466
|
+
const next = await deps.triage([taskRequest(task), ...task.amendments.map((text) => `Amendment: ${text}`)].join("\n\n"), deps.signal);
|
|
467
|
+
if (next) task.triage = next;
|
|
468
|
+
} catch {
|
|
469
|
+
// Hints only: the old triage stays.
|
|
470
|
+
}
|
|
425
471
|
}
|
|
426
472
|
|
|
427
473
|
/** States in which `plan` replaces an approved plan instead of recording the first one. */
|
|
@@ -570,6 +616,8 @@ function workerRequest(deps: WorkflowDeps, task: Task, domain: Domain, instructi
|
|
|
570
616
|
profile: deps.profile,
|
|
571
617
|
signal: deps.signal,
|
|
572
618
|
onUpdate: deps.onUpdate,
|
|
619
|
+
...(deps.hints ? { hints: deps.hints } : {}),
|
|
620
|
+
...(deps.effort ? { effort: deps.effort } : {}),
|
|
573
621
|
};
|
|
574
622
|
}
|
|
575
623
|
|