@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.
Files changed (49) hide show
  1. package/README.md +177 -799
  2. package/package.json +1 -1
  3. package/prompts/master.md +17 -0
  4. package/prompts/panel.md +3 -1
  5. package/prompts/planner.md +14 -0
  6. package/prompts/quickfix.md +3 -1
  7. package/prompts/scout.md +3 -0
  8. package/prompts/worker.md +3 -0
  9. package/src/classifier/answers.ts +110 -0
  10. package/src/classifier/classifier.ts +171 -0
  11. package/src/classifier/client.ts +239 -0
  12. package/src/classifier/effort.ts +143 -0
  13. package/src/classifier/files.ts +427 -0
  14. package/src/classifier/hosts.ts +157 -0
  15. package/src/classifier/instance.ts +98 -0
  16. package/src/classifier/limits.ts +37 -0
  17. package/src/classifier/seats.ts +102 -0
  18. package/src/classifier/tools.ts +58 -0
  19. package/src/classifier/triage.ts +203 -0
  20. package/src/execution/agent-runner.ts +5 -0
  21. package/src/index.ts +6 -0
  22. package/src/lobby/keys.ts +1 -1
  23. package/src/lobby/planner.ts +305 -27
  24. package/src/lobby/quickfix.ts +120 -8
  25. package/src/lobby/runtime.ts +136 -5
  26. package/src/lobby/session-files.ts +12 -0
  27. package/src/lobby/sessions.ts +28 -2
  28. package/src/lobby/tabs/home.ts +54 -26
  29. package/src/lobby/tabs/metrics.ts +28 -1
  30. package/src/lobby/tabs/plan.ts +27 -4
  31. package/src/lobby/tabs/quickfix.ts +5 -1
  32. package/src/lobby/tabs/tasks.ts +30 -14
  33. package/src/lobby/view.ts +334 -41
  34. package/src/master/master.ts +95 -29
  35. package/src/pi/commands.ts +24 -4
  36. package/src/pi/events.ts +11 -2
  37. package/src/pi/owner.ts +57 -8
  38. package/src/pi/run-summary.ts +3 -1
  39. package/src/pi/settings-ui.ts +138 -2
  40. package/src/pi/start-task.ts +4 -0
  41. package/src/pi/tools.ts +7 -2
  42. package/src/schemas/configuration.ts +125 -1
  43. package/src/schemas/findings.ts +4 -0
  44. package/src/schemas/task.ts +24 -0
  45. package/src/state/archive.ts +99 -0
  46. package/src/state/inbox.ts +49 -15
  47. package/src/state/metrics.ts +74 -1
  48. package/src/state/presence.ts +99 -0
  49. package/src/workflow/workflow.ts +49 -1
@@ -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
- return applyApprovalChoice(task, "amend", await deps.ask("What should change?"));
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