agent-bober 0.17.1 → 0.18.0
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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +158 -5
- package/dist/chat/answerer.d.ts +17 -0
- package/dist/chat/answerer.d.ts.map +1 -0
- package/dist/chat/answerer.js +52 -0
- package/dist/chat/answerer.js.map +1 -0
- package/dist/chat/approval-cursor.d.ts +25 -0
- package/dist/chat/approval-cursor.d.ts.map +1 -0
- package/dist/chat/approval-cursor.js +61 -0
- package/dist/chat/approval-cursor.js.map +1 -0
- package/dist/chat/approval-reader.d.ts +11 -0
- package/dist/chat/approval-reader.d.ts.map +1 -0
- package/dist/chat/approval-reader.js +20 -0
- package/dist/chat/approval-reader.js.map +1 -0
- package/dist/chat/careful-sidecar.d.ts +15 -0
- package/dist/chat/careful-sidecar.d.ts.map +1 -0
- package/dist/chat/careful-sidecar.js +39 -0
- package/dist/chat/careful-sidecar.js.map +1 -0
- package/dist/chat/chat-session.d.ts +129 -0
- package/dist/chat/chat-session.d.ts.map +1 -0
- package/dist/chat/chat-session.js +470 -0
- package/dist/chat/chat-session.js.map +1 -0
- package/dist/chat/completion-tailer.d.ts +27 -0
- package/dist/chat/completion-tailer.d.ts.map +1 -0
- package/dist/chat/completion-tailer.js +187 -0
- package/dist/chat/completion-tailer.js.map +1 -0
- package/dist/chat/conversation-store.d.ts +22 -0
- package/dist/chat/conversation-store.d.ts.map +1 -0
- package/dist/chat/conversation-store.js +66 -0
- package/dist/chat/conversation-store.js.map +1 -0
- package/dist/chat/cursor-store.d.ts +23 -0
- package/dist/chat/cursor-store.d.ts.map +1 -0
- package/dist/chat/cursor-store.js +42 -0
- package/dist/chat/cursor-store.js.map +1 -0
- package/dist/chat/pid-sidecar.d.ts +22 -0
- package/dist/chat/pid-sidecar.d.ts.map +1 -0
- package/dist/chat/pid-sidecar.js +42 -0
- package/dist/chat/pid-sidecar.js.map +1 -0
- package/dist/chat/roster-reader.d.ts +16 -0
- package/dist/chat/roster-reader.d.ts.map +1 -0
- package/dist/chat/roster-reader.js +39 -0
- package/dist/chat/roster-reader.js.map +1 -0
- package/dist/chat/run-spawner.d.ts +71 -0
- package/dist/chat/run-spawner.d.ts.map +1 -0
- package/dist/chat/run-spawner.js +121 -0
- package/dist/chat/run-spawner.js.map +1 -0
- package/dist/chat/slash-commands.d.ts +36 -0
- package/dist/chat/slash-commands.d.ts.map +1 -0
- package/dist/chat/slash-commands.js +133 -0
- package/dist/chat/slash-commands.js.map +1 -0
- package/dist/chat/steer-cleanup.d.ts +12 -0
- package/dist/chat/steer-cleanup.d.ts.map +1 -0
- package/dist/chat/steer-cleanup.js +60 -0
- package/dist/chat/steer-cleanup.js.map +1 -0
- package/dist/chat/turn-classifier.d.ts +43 -0
- package/dist/chat/turn-classifier.d.ts.map +1 -0
- package/dist/chat/turn-classifier.js +150 -0
- package/dist/chat/turn-classifier.js.map +1 -0
- package/dist/cli/commands/blackboard.d.ts +33 -0
- package/dist/cli/commands/blackboard.d.ts.map +1 -0
- package/dist/cli/commands/blackboard.js +114 -0
- package/dist/cli/commands/blackboard.js.map +1 -0
- package/dist/cli/commands/chat.d.ts +13 -0
- package/dist/cli/commands/chat.d.ts.map +1 -0
- package/dist/cli/commands/chat.js +43 -0
- package/dist/cli/commands/chat.js.map +1 -0
- package/dist/cli/commands/evolve.d.ts +18 -0
- package/dist/cli/commands/evolve.d.ts.map +1 -0
- package/dist/cli/commands/evolve.js +72 -0
- package/dist/cli/commands/evolve.js.map +1 -0
- package/dist/cli/commands/facts.d.ts +15 -0
- package/dist/cli/commands/facts.d.ts.map +1 -0
- package/dist/cli/commands/facts.js +213 -0
- package/dist/cli/commands/facts.js.map +1 -0
- package/dist/cli/commands/medical.d.ts +24 -0
- package/dist/cli/commands/medical.d.ts.map +1 -0
- package/dist/cli/commands/medical.js +132 -0
- package/dist/cli/commands/medical.js.map +1 -0
- package/dist/cli/commands/memory.d.ts +2 -1
- package/dist/cli/commands/memory.d.ts.map +1 -1
- package/dist/cli/commands/memory.js +94 -7
- package/dist/cli/commands/memory.js.map +1 -1
- package/dist/cli/commands/plan.d.ts.map +1 -1
- package/dist/cli/commands/plan.js +29 -3
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/replay.d.ts +17 -0
- package/dist/cli/commands/replay.d.ts.map +1 -0
- package/dist/cli/commands/replay.js +261 -0
- package/dist/cli/commands/replay.js.map +1 -0
- package/dist/cli/commands/run.d.ts +9 -0
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +27 -1
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/sprint.d.ts.map +1 -1
- package/dist/cli/commands/sprint.js +17 -3
- package/dist/cli/commands/sprint.js.map +1 -1
- package/dist/cli/index.js +12 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +8 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/role-providers.d.ts +1 -1
- package/dist/config/role-providers.d.ts.map +1 -1
- package/dist/config/role-providers.js +6 -1
- package/dist/config/role-providers.js.map +1 -1
- package/dist/config/schema.d.ts +467 -222
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +25 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/contracts/eval-result.d.ts +84 -84
- package/dist/contracts/spec.d.ts +28 -28
- package/dist/contracts/sprint-contract.d.ts +4 -4
- package/dist/fleet/critic-deep.d.ts +53 -0
- package/dist/fleet/critic-deep.d.ts.map +1 -0
- package/dist/fleet/critic-deep.js +199 -0
- package/dist/fleet/critic-deep.js.map +1 -0
- package/dist/fleet/decomposer-deep-constants.d.ts +4 -0
- package/dist/fleet/decomposer-deep-constants.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep-constants.js +14 -0
- package/dist/fleet/decomposer-deep-constants.js.map +1 -0
- package/dist/fleet/decomposer-deep-types.d.ts +8 -0
- package/dist/fleet/decomposer-deep-types.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep-types.js +9 -0
- package/dist/fleet/decomposer-deep-types.js.map +1 -0
- package/dist/fleet/decomposer-deep.d.ts +51 -0
- package/dist/fleet/decomposer-deep.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep.js +261 -0
- package/dist/fleet/decomposer-deep.js.map +1 -0
- package/dist/fleet/decomposer.d.ts +22 -0
- package/dist/fleet/decomposer.d.ts.map +1 -0
- package/dist/fleet/decomposer.js +144 -0
- package/dist/fleet/decomposer.js.map +1 -0
- package/dist/fleet/index.d.ts +93 -0
- package/dist/fleet/index.d.ts.map +1 -1
- package/dist/fleet/index.js +230 -2
- package/dist/fleet/index.js.map +1 -1
- package/dist/fleet/manifest-write.d.ts +30 -0
- package/dist/fleet/manifest-write.d.ts.map +1 -0
- package/dist/fleet/manifest-write.js +90 -0
- package/dist/fleet/manifest-write.js.map +1 -0
- package/dist/fleet/manifest.d.ts +6 -6
- package/dist/fleet/shared-blackboard.d.ts +51 -0
- package/dist/fleet/shared-blackboard.d.ts.map +1 -0
- package/dist/fleet/shared-blackboard.js +79 -0
- package/dist/fleet/shared-blackboard.js.map +1 -0
- package/dist/fleet/synthesis.d.ts +16 -0
- package/dist/fleet/synthesis.d.ts.map +1 -0
- package/dist/fleet/synthesis.js +22 -0
- package/dist/fleet/synthesis.js.map +1 -0
- package/dist/fleet/tier-policy.d.ts +18 -0
- package/dist/fleet/tier-policy.d.ts.map +1 -0
- package/dist/fleet/tier-policy.js +53 -0
- package/dist/fleet/tier-policy.js.map +1 -0
- package/dist/fleet/tool-role-guard.d.ts +24 -0
- package/dist/fleet/tool-role-guard.d.ts.map +1 -0
- package/dist/fleet/tool-role-guard.js +55 -0
- package/dist/fleet/tool-role-guard.js.map +1 -0
- package/dist/incident/resolution-verify.d.ts +4 -4
- package/dist/incident/types.d.ts +8 -8
- package/dist/mcp/run-manager.d.ts +9 -1
- package/dist/mcp/run-manager.d.ts.map +1 -1
- package/dist/mcp/run-manager.js.map +1 -1
- package/dist/medical/adapters/apple-health.d.ts +32 -0
- package/dist/medical/adapters/apple-health.d.ts.map +1 -0
- package/dist/medical/adapters/apple-health.js +100 -0
- package/dist/medical/adapters/apple-health.js.map +1 -0
- package/dist/medical/audit.d.ts +31 -0
- package/dist/medical/audit.d.ts.map +1 -0
- package/dist/medical/audit.js +56 -0
- package/dist/medical/audit.js.map +1 -0
- package/dist/medical/consent.d.ts +37 -0
- package/dist/medical/consent.d.ts.map +1 -0
- package/dist/medical/consent.js +73 -0
- package/dist/medical/consent.js.map +1 -0
- package/dist/medical/disclaimer.d.ts +11 -0
- package/dist/medical/disclaimer.d.ts.map +1 -0
- package/dist/medical/disclaimer.js +21 -0
- package/dist/medical/disclaimer.js.map +1 -0
- package/dist/medical/egress.d.ts +30 -0
- package/dist/medical/egress.d.ts.map +1 -0
- package/dist/medical/egress.js +50 -0
- package/dist/medical/egress.js.map +1 -0
- package/dist/medical/engine.d.ts +73 -0
- package/dist/medical/engine.d.ts.map +1 -0
- package/dist/medical/engine.js +333 -0
- package/dist/medical/engine.js.map +1 -0
- package/dist/medical/guardrails.d.ts +47 -0
- package/dist/medical/guardrails.d.ts.map +1 -0
- package/dist/medical/guardrails.js +92 -0
- package/dist/medical/guardrails.js.map +1 -0
- package/dist/medical/health-store.d.ts +80 -0
- package/dist/medical/health-store.d.ts.map +1 -0
- package/dist/medical/health-store.js +204 -0
- package/dist/medical/health-store.js.map +1 -0
- package/dist/medical/inference.d.ts +22 -0
- package/dist/medical/inference.d.ts.map +1 -0
- package/dist/medical/inference.js +39 -0
- package/dist/medical/inference.js.map +1 -0
- package/dist/medical/ingestion.d.ts +33 -0
- package/dist/medical/ingestion.d.ts.map +1 -0
- package/dist/medical/ingestion.js +52 -0
- package/dist/medical/ingestion.js.map +1 -0
- package/dist/medical/numerics.d.ts +66 -0
- package/dist/medical/numerics.d.ts.map +1 -0
- package/dist/medical/numerics.js +216 -0
- package/dist/medical/numerics.js.map +1 -0
- package/dist/medical/red-flag.d.ts +42 -0
- package/dist/medical/red-flag.d.ts.map +1 -0
- package/dist/medical/red-flag.js +161 -0
- package/dist/medical/red-flag.js.map +1 -0
- package/dist/medical/refusal.d.ts +46 -0
- package/dist/medical/refusal.d.ts.map +1 -0
- package/dist/medical/refusal.js +131 -0
- package/dist/medical/refusal.js.map +1 -0
- package/dist/medical/retrieval/grounding-critic.d.ts +34 -0
- package/dist/medical/retrieval/grounding-critic.d.ts.map +1 -0
- package/dist/medical/retrieval/grounding-critic.js +153 -0
- package/dist/medical/retrieval/grounding-critic.js.map +1 -0
- package/dist/medical/retrieval/literature.d.ts +78 -0
- package/dist/medical/retrieval/literature.d.ts.map +1 -0
- package/dist/medical/retrieval/literature.js +292 -0
- package/dist/medical/retrieval/literature.js.map +1 -0
- package/dist/medical/retrieval/medline-source.d.ts +72 -0
- package/dist/medical/retrieval/medline-source.d.ts.map +1 -0
- package/dist/medical/retrieval/medline-source.js +120 -0
- package/dist/medical/retrieval/medline-source.js.map +1 -0
- package/dist/medical/team.d.ts +15 -0
- package/dist/medical/team.d.ts.map +1 -0
- package/dist/medical/team.js +44 -0
- package/dist/medical/team.js.map +1 -0
- package/dist/medical/types.d.ts +175 -0
- package/dist/medical/types.d.ts.map +1 -0
- package/dist/medical/types.js +8 -0
- package/dist/medical/types.js.map +1 -0
- package/dist/medical/whoop/whoop-client.d.ts +114 -0
- package/dist/medical/whoop/whoop-client.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-client.js +226 -0
- package/dist/medical/whoop/whoop-client.js.map +1 -0
- package/dist/medical/whoop/whoop-sync.d.ts +25 -0
- package/dist/medical/whoop/whoop-sync.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-sync.js +97 -0
- package/dist/medical/whoop/whoop-sync.js.map +1 -0
- package/dist/medical/whoop/whoop-token.d.ts +44 -0
- package/dist/medical/whoop/whoop-token.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-token.js +66 -0
- package/dist/medical/whoop/whoop-token.js.map +1 -0
- package/dist/orchestrator/context-handoff.d.ts +60 -60
- package/dist/orchestrator/contract-materialization.d.ts +33 -0
- package/dist/orchestrator/contract-materialization.d.ts.map +1 -0
- package/dist/orchestrator/contract-materialization.js +113 -0
- package/dist/orchestrator/contract-materialization.js.map +1 -0
- package/dist/orchestrator/memory/distill.d.ts +4 -1
- package/dist/orchestrator/memory/distill.d.ts.map +1 -1
- package/dist/orchestrator/memory/distill.js +41 -1
- package/dist/orchestrator/memory/distill.js.map +1 -1
- package/dist/orchestrator/memory/fact-detector.d.ts +61 -0
- package/dist/orchestrator/memory/fact-detector.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-detector.js +153 -0
- package/dist/orchestrator/memory/fact-detector.js.map +1 -0
- package/dist/orchestrator/memory/fact-judge.d.ts +19 -0
- package/dist/orchestrator/memory/fact-judge.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-judge.js +121 -0
- package/dist/orchestrator/memory/fact-judge.js.map +1 -0
- package/dist/orchestrator/memory/fact-retrieve.d.ts +52 -0
- package/dist/orchestrator/memory/fact-retrieve.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-retrieve.js +117 -0
- package/dist/orchestrator/memory/fact-retrieve.js.map +1 -0
- package/dist/orchestrator/memory/hygiene.d.ts +66 -0
- package/dist/orchestrator/memory/hygiene.d.ts.map +1 -0
- package/dist/orchestrator/memory/hygiene.js +153 -0
- package/dist/orchestrator/memory/hygiene.js.map +1 -0
- package/dist/orchestrator/memory/reconcile.d.ts +47 -0
- package/dist/orchestrator/memory/reconcile.d.ts.map +1 -0
- package/dist/orchestrator/memory/reconcile.js +116 -0
- package/dist/orchestrator/memory/reconcile.js.map +1 -0
- package/dist/orchestrator/memory/retrieve.d.ts +5 -3
- package/dist/orchestrator/memory/retrieve.d.ts.map +1 -1
- package/dist/orchestrator/memory/retrieve.js +9 -6
- package/dist/orchestrator/memory/retrieve.js.map +1 -1
- package/dist/orchestrator/pipeline.d.ts +19 -3
- package/dist/orchestrator/pipeline.d.ts.map +1 -1
- package/dist/orchestrator/pipeline.js +63 -52
- package/dist/orchestrator/pipeline.js.map +1 -1
- package/dist/orchestrator/planner-agent.d.ts.map +1 -1
- package/dist/orchestrator/planner-agent.js +16 -1
- package/dist/orchestrator/planner-agent.js.map +1 -1
- package/dist/orchestrator/selfimprove/eval-guards.d.ts +51 -0
- package/dist/orchestrator/selfimprove/eval-guards.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/eval-guards.js +120 -0
- package/dist/orchestrator/selfimprove/eval-guards.js.map +1 -0
- package/dist/orchestrator/selfimprove/gepa.d.ts +74 -0
- package/dist/orchestrator/selfimprove/gepa.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/gepa.js +227 -0
- package/dist/orchestrator/selfimprove/gepa.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-harness.d.ts +65 -0
- package/dist/orchestrator/selfimprove/replay-harness.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-harness.js +134 -0
- package/dist/orchestrator/selfimprove/replay-harness.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-store.d.ts +45 -0
- package/dist/orchestrator/selfimprove/replay-store.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-store.js +119 -0
- package/dist/orchestrator/selfimprove/replay-store.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-types.d.ts +32 -0
- package/dist/orchestrator/selfimprove/replay-types.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-types.js +15 -0
- package/dist/orchestrator/selfimprove/replay-types.js.map +1 -0
- package/dist/orchestrator/workflow/engine.d.ts +3 -1
- package/dist/orchestrator/workflow/engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/selector.d.ts +18 -0
- package/dist/orchestrator/workflow/selector.d.ts.map +1 -1
- package/dist/orchestrator/workflow/selector.js +41 -0
- package/dist/orchestrator/workflow/selector.js.map +1 -1
- package/dist/orchestrator/workflow/ts-engine.d.ts +3 -1
- package/dist/orchestrator/workflow/ts-engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/ts-engine.js +2 -2
- package/dist/orchestrator/workflow/ts-engine.js.map +1 -1
- package/dist/orchestrator/workflow/workflow-engine.d.ts +3 -1
- package/dist/orchestrator/workflow/workflow-engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/workflow-engine.js +3 -3
- package/dist/orchestrator/workflow/workflow-engine.js.map +1 -1
- package/dist/state/facts.d.ts +110 -0
- package/dist/state/facts.d.ts.map +1 -0
- package/dist/state/facts.js +208 -0
- package/dist/state/facts.js.map +1 -0
- package/dist/state/guidance.d.ts +37 -0
- package/dist/state/guidance.d.ts.map +1 -0
- package/dist/state/guidance.js +144 -0
- package/dist/state/guidance.js.map +1 -0
- package/dist/state/history.d.ts +2 -2
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +1 -1
- package/dist/state/index.js.map +1 -1
- package/dist/state/memory.d.ts +43 -11
- package/dist/state/memory.d.ts.map +1 -1
- package/dist/state/memory.js +93 -15
- package/dist/state/memory.js.map +1 -1
- package/dist/state/pause.d.ts +47 -0
- package/dist/state/pause.d.ts.map +1 -0
- package/dist/state/pause.js +146 -0
- package/dist/state/pause.js.map +1 -0
- package/dist/state/sprint-state.d.ts +8 -0
- package/dist/state/sprint-state.d.ts.map +1 -1
- package/dist/state/sprint-state.js +32 -1
- package/dist/state/sprint-state.js.map +1 -1
- package/dist/teams/registry.d.ts +16 -0
- package/dist/teams/registry.d.ts.map +1 -0
- package/dist/teams/registry.js +53 -0
- package/dist/teams/registry.js.map +1 -0
- package/dist/teams/types.d.ts +25 -0
- package/dist/teams/types.d.ts.map +1 -0
- package/dist/teams/types.js +2 -0
- package/dist/teams/types.js.map +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as readline from "node:readline";
|
|
2
|
+
import type { LLMClient } from "../providers/types.js";
|
|
3
|
+
import { RunSpawner } from "./run-spawner.js";
|
|
4
|
+
import { CompletionTailer } from "./completion-tailer.js";
|
|
5
|
+
import { ApprovalReader } from "./approval-reader.js";
|
|
6
|
+
export interface ChatSessionOptions {
|
|
7
|
+
llm: LLMClient;
|
|
8
|
+
projectRoot: string;
|
|
9
|
+
sessionId?: string;
|
|
10
|
+
/** Override readline interface for testing (omit to use stdin/stdout). */
|
|
11
|
+
rl?: readline.Interface;
|
|
12
|
+
/** Injected RunSpawner for testing (omit to use a real instance). */
|
|
13
|
+
spawner?: RunSpawner;
|
|
14
|
+
/** Injected clock for deterministic runId generation in tests. */
|
|
15
|
+
now?: () => number;
|
|
16
|
+
/** Injected CompletionTailer for testing (omit to use a real instance). */
|
|
17
|
+
tailer?: CompletionTailer;
|
|
18
|
+
/** Injected ApprovalReader for testing (omit to use a real instance). */
|
|
19
|
+
approvalReader?: ApprovalReader;
|
|
20
|
+
/**
|
|
21
|
+
* Memory namespace for the active team. Omit (or pass "") for the default
|
|
22
|
+
* programming team, which resolves to the current .bober/memory/ path.
|
|
23
|
+
* Sprint 2: threaded through buildMemoryDistill so a named team reads its own subdir.
|
|
24
|
+
*/
|
|
25
|
+
memoryNamespace?: string;
|
|
26
|
+
}
|
|
27
|
+
export declare class ChatSession {
|
|
28
|
+
private readonly llm;
|
|
29
|
+
private readonly projectRoot;
|
|
30
|
+
private readonly sessionId;
|
|
31
|
+
private readonly store;
|
|
32
|
+
private readonly roster;
|
|
33
|
+
private readonly classifier;
|
|
34
|
+
private readonly answerer;
|
|
35
|
+
private readonly spawner;
|
|
36
|
+
private readonly tailer;
|
|
37
|
+
private readonly approvalReader;
|
|
38
|
+
private readonly approvalCursor;
|
|
39
|
+
private readonly nowFn;
|
|
40
|
+
private readonly model;
|
|
41
|
+
/** Memory namespace for the active team; undefined means the default .bober/memory/ path. */
|
|
42
|
+
private readonly memoryNamespace;
|
|
43
|
+
/** Phase 2: persists the per-session careful-mode toggle. */
|
|
44
|
+
private readonly carefulSidecar;
|
|
45
|
+
constructor(opts: ChatSessionOptions);
|
|
46
|
+
/** Generate a session-scoped runId using the injected clock. */
|
|
47
|
+
private nextRunId;
|
|
48
|
+
/**
|
|
49
|
+
* Handle a single turn: slash-dispatch or classify→answer→persist.
|
|
50
|
+
* Returns the assistant reply string, or null for /exit.
|
|
51
|
+
*/
|
|
52
|
+
handleTurn(input: string): Promise<string | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Stop a run by resolving it against the current disk roster, then calling
|
|
55
|
+
* RunSpawner.stop. Shared by /stop <runId> (deterministic slash path) and
|
|
56
|
+
* classifier steer:stop (natural-language path). Never reaches the LLM.
|
|
57
|
+
*/
|
|
58
|
+
private handleStop;
|
|
59
|
+
/**
|
|
60
|
+
* Handle /careful [on|off].
|
|
61
|
+
* - "on" → set careful true, return confirmation
|
|
62
|
+
* - "off" → set careful false, return confirmation
|
|
63
|
+
* - undefined/other → report current state
|
|
64
|
+
*/
|
|
65
|
+
private handleCareful;
|
|
66
|
+
/**
|
|
67
|
+
* Approve a pending checkpoint: guard with pendingExists, write the marker,
|
|
68
|
+
* clear the correlated RunState pending fields, and return an ack string.
|
|
69
|
+
* Returns a "no pending checkpoint" message and writes nothing if the pending
|
|
70
|
+
* file does not exist (sc-3-4).
|
|
71
|
+
*/
|
|
72
|
+
private handleApprove;
|
|
73
|
+
/**
|
|
74
|
+
* Reject a pending checkpoint: guard with pendingExists, write the marker
|
|
75
|
+
* carrying the feedback string, clear the correlated RunState, and return ack.
|
|
76
|
+
* Returns a "no pending checkpoint" message and writes nothing if absent (sc-3-4).
|
|
77
|
+
*/
|
|
78
|
+
private handleReject;
|
|
79
|
+
/**
|
|
80
|
+
* Queue free-text guidance for a run at the next pipeline boundary.
|
|
81
|
+
* Shared by /tell <runId> <text> (deterministic slash path) and
|
|
82
|
+
* classifier tell (natural-language path). Never reaches the LLM.
|
|
83
|
+
*
|
|
84
|
+
* Guards: unknown run (not in roster) → clear error, writes nothing.
|
|
85
|
+
* Path-traversal: appendGuidance validates runId via safeSegment first.
|
|
86
|
+
* Does NOT require careful mode; guidance can be queued for any known run.
|
|
87
|
+
*/
|
|
88
|
+
private handleTell;
|
|
89
|
+
/**
|
|
90
|
+
* Soft-pause a run at the next checkpoint boundary.
|
|
91
|
+
*
|
|
92
|
+
* Distinct from handleStop: this does NOT send a kill signal — the process
|
|
93
|
+
* stays alive and will hold at the next cooperative-pause gate in the pipeline.
|
|
94
|
+
*
|
|
95
|
+
* Guards: run must be found in the roster with status "running".
|
|
96
|
+
* Side effects: writes paused.json marker + flips chat-owned RunState to
|
|
97
|
+
* 'paused' (with pausedAt timestamp) via writeRunState.
|
|
98
|
+
*/
|
|
99
|
+
private handlePause;
|
|
100
|
+
/**
|
|
101
|
+
* Resume a soft-paused run.
|
|
102
|
+
*
|
|
103
|
+
* Clears the paused.json marker (best-effort) and flips RunState back
|
|
104
|
+
* to 'running' (dropping the pausedAt field). The pipeline's cooperative
|
|
105
|
+
* gate polls isPaused, so removing the marker allows the gate to advance.
|
|
106
|
+
*/
|
|
107
|
+
private handleResume;
|
|
108
|
+
/**
|
|
109
|
+
* Clear pending fields from the RunState correlated to this checkpoint.
|
|
110
|
+
* Inverse of the Sprint 2 reflection block: finds the input-required RunState
|
|
111
|
+
* matching this checkpointId, drops the three pending fields, and sets
|
|
112
|
+
* status back to "running". Idempotent — no-op if no correlated state exists.
|
|
113
|
+
*/
|
|
114
|
+
private clearPending;
|
|
115
|
+
/**
|
|
116
|
+
* Resolve a checkpoint id for NL approve/reject paths.
|
|
117
|
+
* - If an id is provided, use it directly.
|
|
118
|
+
* - If exactly one pending marker exists, use it.
|
|
119
|
+
* - If zero or multiple pending markers exist (without a named id), return
|
|
120
|
+
* an ambiguous result so the caller can ask the user instead of guessing.
|
|
121
|
+
*/
|
|
122
|
+
private resolveCheckpoint;
|
|
123
|
+
/**
|
|
124
|
+
* Start an interactive REPL loop reading from stdin.
|
|
125
|
+
* Use handleTurn() directly in tests instead.
|
|
126
|
+
*/
|
|
127
|
+
start(): Promise<void>;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=chat-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../../src/chat/chat-session.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAiBtD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,SAAS,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,EAAE,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC;IACxB,qEAAqE;IACrE,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,yEAAyE;IACzE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AA+BD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiB;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;gBAEpC,IAAI,EAAE,kBAAkB;IAyBpC,gEAAgE;IAChE,OAAO,CAAC,SAAS;IAIjB;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgKvD;;;;OAIG;YACW,UAAU;IAYxB;;;;;OAKG;YACW,aAAa;IAa3B;;;;;OAKG;YACW,aAAa;IAa3B;;;;OAIG;YACW,YAAY;IAc1B;;;;;;;;OAQG;YACW,UAAU;IAexB;;;;;;;;;OASG;YACW,WAAW;IAazB;;;;;;OAMG;YACW,YAAY;IAa1B;;;;;OAKG;YACW,YAAY;IAe1B;;;;;;OAMG;YACW,iBAAiB;IAgB/B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAyC7B"}
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
// ── chat-session.ts ───────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// ChatSession: the main turn loop for `bober chat`.
|
|
4
|
+
// Per turn: classify → answer (or slash-dispatch) → persist.
|
|
5
|
+
import * as readline from "node:readline";
|
|
6
|
+
import { loadLessonIndex, loadLesson } from "../state/memory.js";
|
|
7
|
+
import { ConversationStore } from "./conversation-store.js";
|
|
8
|
+
import { RosterReader } from "./roster-reader.js";
|
|
9
|
+
import { TurnClassifier } from "./turn-classifier.js";
|
|
10
|
+
import { Answerer } from "./answerer.js";
|
|
11
|
+
import { dispatch } from "./slash-commands.js";
|
|
12
|
+
import { RunSpawner } from "./run-spawner.js";
|
|
13
|
+
import { CarefulSidecar } from "./careful-sidecar.js";
|
|
14
|
+
import { CompletionTailer } from "./completion-tailer.js";
|
|
15
|
+
import { ApprovalReader } from "./approval-reader.js";
|
|
16
|
+
import { ApprovalCursor } from "./approval-cursor.js";
|
|
17
|
+
import { writeRunState } from "../state/run-state.js";
|
|
18
|
+
import { saveApproved, saveRejected, pendingExists, } from "../state/approval-state.js";
|
|
19
|
+
import { appendGuidance, hasRunDir } from "../state/guidance.js";
|
|
20
|
+
import { setPaused, clearPaused } from "../state/pause.js";
|
|
21
|
+
import { resolveApprover } from "../cli/commands/approve.js";
|
|
22
|
+
import { cleanupTerminalRun } from "./steer-cleanup.js";
|
|
23
|
+
import { seedProjectFacts } from "../orchestrator/memory/fact-detector.js";
|
|
24
|
+
// ── Memory distill helper ─────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* Compose a compact memory distill string from the team's namespaced .bober/memory/ path.
|
|
27
|
+
* Returns empty string if no lessons are recorded.
|
|
28
|
+
* namespace undefined or "" reads the default .bober/memory/ path (programming team / back-compat).
|
|
29
|
+
*/
|
|
30
|
+
async function buildMemoryDistill(projectRoot, namespace) {
|
|
31
|
+
try {
|
|
32
|
+
const index = await loadLessonIndex(projectRoot, { limit: 10 }, namespace);
|
|
33
|
+
if (index.length === 0)
|
|
34
|
+
return "";
|
|
35
|
+
const lines = ["Recent lessons learned:"];
|
|
36
|
+
for (const record of index) {
|
|
37
|
+
try {
|
|
38
|
+
const lesson = await loadLesson(projectRoot, record.lessonId, namespace);
|
|
39
|
+
lines.push(`- [${lesson.severity}] ${lesson.summary}`);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
lines.push(`- ${record.summarySnippet}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return lines.join("\n");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// ── ChatSession ───────────────────────────────────────────────────────
|
|
52
|
+
export class ChatSession {
|
|
53
|
+
llm;
|
|
54
|
+
projectRoot;
|
|
55
|
+
sessionId;
|
|
56
|
+
store;
|
|
57
|
+
roster;
|
|
58
|
+
classifier;
|
|
59
|
+
answerer;
|
|
60
|
+
spawner;
|
|
61
|
+
tailer;
|
|
62
|
+
approvalReader;
|
|
63
|
+
approvalCursor;
|
|
64
|
+
nowFn;
|
|
65
|
+
// bober: using "opus" as default model; the CLI wires in config.chat?.model via createClient
|
|
66
|
+
model = "opus";
|
|
67
|
+
/** Memory namespace for the active team; undefined means the default .bober/memory/ path. */
|
|
68
|
+
memoryNamespace;
|
|
69
|
+
/** Phase 2: persists the per-session careful-mode toggle. */
|
|
70
|
+
carefulSidecar;
|
|
71
|
+
constructor(opts) {
|
|
72
|
+
this.llm = opts.llm;
|
|
73
|
+
this.projectRoot = opts.projectRoot;
|
|
74
|
+
this.sessionId = opts.sessionId ?? "default";
|
|
75
|
+
this.memoryNamespace = opts.memoryNamespace || undefined;
|
|
76
|
+
this.store = new ConversationStore(this.projectRoot, this.sessionId);
|
|
77
|
+
this.roster = new RosterReader(this.projectRoot);
|
|
78
|
+
this.classifier = new TurnClassifier(this.llm, this.model);
|
|
79
|
+
this.answerer = new Answerer(this.llm, this.model);
|
|
80
|
+
this.nowFn = opts.now ?? (() => Date.now());
|
|
81
|
+
this.spawner =
|
|
82
|
+
opts.spawner ??
|
|
83
|
+
new RunSpawner({
|
|
84
|
+
projectRoot: this.projectRoot,
|
|
85
|
+
sessionId: this.sessionId,
|
|
86
|
+
});
|
|
87
|
+
this.tailer =
|
|
88
|
+
opts.tailer ??
|
|
89
|
+
new CompletionTailer(this.projectRoot, this.sessionId);
|
|
90
|
+
this.approvalReader =
|
|
91
|
+
opts.approvalReader ?? new ApprovalReader(this.projectRoot);
|
|
92
|
+
this.approvalCursor = new ApprovalCursor(this.projectRoot, this.sessionId);
|
|
93
|
+
this.carefulSidecar = new CarefulSidecar(this.projectRoot, this.sessionId);
|
|
94
|
+
}
|
|
95
|
+
/** Generate a session-scoped runId using the injected clock. */
|
|
96
|
+
nextRunId() {
|
|
97
|
+
return `run-${this.nowFn()}`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Handle a single turn: slash-dispatch or classify→answer→persist.
|
|
101
|
+
* Returns the assistant reply string, or null for /exit.
|
|
102
|
+
*/
|
|
103
|
+
async handleTurn(input) {
|
|
104
|
+
// ── Poll for run completions (prelude — runs before slash or LLM path) ─
|
|
105
|
+
let completions = [];
|
|
106
|
+
try {
|
|
107
|
+
completions = await this.tailer.poll();
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Poll errors must never break the turn
|
|
111
|
+
}
|
|
112
|
+
// ── Cleanup hygiene for runs that just went terminal (Sprint 6) ────────
|
|
113
|
+
for (const c of completions) {
|
|
114
|
+
if (c.runId) {
|
|
115
|
+
try {
|
|
116
|
+
await cleanupTerminalRun(this.projectRoot, c.runId);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// best-effort — a cleanup failure must never break the turn
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ── Poll for pending approvals (prelude) ──────────────────────────────
|
|
124
|
+
let approvalNotice = "";
|
|
125
|
+
try {
|
|
126
|
+
const pending = await this.approvalReader.read();
|
|
127
|
+
if (pending.length > 0) {
|
|
128
|
+
const fresh = await this.approvalCursor.filterNew(pending);
|
|
129
|
+
if (fresh.length > 0) {
|
|
130
|
+
// Reflect correlated markers onto running RunStates (idempotent)
|
|
131
|
+
const states = await this.roster.read();
|
|
132
|
+
for (const m of fresh) {
|
|
133
|
+
if (m.runId) {
|
|
134
|
+
const state = states.find((s) => s.runId === m.runId && s.status === "running");
|
|
135
|
+
if (state) {
|
|
136
|
+
await writeRunState(this.projectRoot, {
|
|
137
|
+
...state,
|
|
138
|
+
status: "input-required",
|
|
139
|
+
pendingCheckpointId: m.checkpointId,
|
|
140
|
+
pendingPrompt: m.prompt,
|
|
141
|
+
pendingSince: m.requestedAt,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Build the notice string
|
|
147
|
+
const notices = fresh
|
|
148
|
+
.map((m) => `[run ${m.runId ?? "unknown"} waiting at ${m.checkpointId}: ${m.prompt}]`)
|
|
149
|
+
.join("\n");
|
|
150
|
+
approvalNotice = notices;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Approval read errors must never break the turn
|
|
156
|
+
}
|
|
157
|
+
// ── Slash commands (deterministic, no LLM) ─────────────────────────
|
|
158
|
+
const slashResult = await dispatch(input, this.roster, (runId) => this.handleStop(runId), (arg) => this.handleCareful(arg), (id) => this.handleApprove(id), (id, fb) => this.handleReject(id, fb), (runId, text) => this.handleTell(runId, text), (runId) => this.handlePause(runId), (runId) => this.handleResume(runId));
|
|
159
|
+
if (slashResult.handled) {
|
|
160
|
+
if (slashResult.exit)
|
|
161
|
+
return null;
|
|
162
|
+
let output = slashResult.output ?? "";
|
|
163
|
+
// Weave completion notices into slash-command reply as well
|
|
164
|
+
if (completions.length > 0) {
|
|
165
|
+
const notices = completions
|
|
166
|
+
.map((c) => `[run ${c.runId ?? "unknown"} finished: ${c.phase}]`)
|
|
167
|
+
.join("\n");
|
|
168
|
+
output = `${notices}\n\n${output}`;
|
|
169
|
+
}
|
|
170
|
+
// Weave approval notices into slash-command reply
|
|
171
|
+
if (approvalNotice) {
|
|
172
|
+
output = `${approvalNotice}\n\n${output}`;
|
|
173
|
+
}
|
|
174
|
+
// Persist slash command turns for transparency
|
|
175
|
+
await this.store.append({ role: "user", content: input, ts: new Date().toISOString() });
|
|
176
|
+
await this.store.append({ role: "assistant", content: output, ts: new Date().toISOString() });
|
|
177
|
+
return output;
|
|
178
|
+
}
|
|
179
|
+
// ── LLM path: read context ────────────────────────────────────────
|
|
180
|
+
const [states, memoryDistill, recentHistory] = await Promise.all([
|
|
181
|
+
this.roster.read(),
|
|
182
|
+
buildMemoryDistill(this.projectRoot, this.memoryNamespace),
|
|
183
|
+
this.store.loadRecent(20),
|
|
184
|
+
]);
|
|
185
|
+
const rosterSummary = this.roster.summarize(states);
|
|
186
|
+
// ── Classify ──────────────────────────────────────────────────────
|
|
187
|
+
const action = await this.classifier.classify(input);
|
|
188
|
+
let reply;
|
|
189
|
+
if (action.action === "answer") {
|
|
190
|
+
reply = await this.answerer.answer(input, rosterSummary, memoryDistill, recentHistory);
|
|
191
|
+
}
|
|
192
|
+
else if (action.action === "spawn") {
|
|
193
|
+
const runId = this.nextRunId();
|
|
194
|
+
const careful = await this.carefulSidecar.isCareful();
|
|
195
|
+
const ack = await this.spawner.spawn(action.task, runId, { careful });
|
|
196
|
+
reply = ack.spawnError
|
|
197
|
+
? `Failed to launch run ${runId}: ${ack.spawnError}`
|
|
198
|
+
: `Launched run ${runId} for: ${action.task}. Use /runs to track it.`;
|
|
199
|
+
}
|
|
200
|
+
else if (action.action === "steer") {
|
|
201
|
+
if (action.op === "inspect") {
|
|
202
|
+
reply = this.roster.summarize(states);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
// op === "stop", action.runId: string
|
|
206
|
+
reply = await this.handleStop(action.runId);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else if (action.action === "approve" || action.action === "reject") {
|
|
210
|
+
const target = await this.resolveCheckpoint(action.checkpointId);
|
|
211
|
+
if (target.kind === "ambiguous") {
|
|
212
|
+
reply = target.message;
|
|
213
|
+
}
|
|
214
|
+
else if (action.action === "approve") {
|
|
215
|
+
reply = await this.handleApprove(target.id);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
reply = await this.handleReject(target.id, action.feedback ?? "");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (action.action === "tell") {
|
|
222
|
+
reply = await this.handleTell(action.runId, action.text);
|
|
223
|
+
}
|
|
224
|
+
else if (action.action === "pause") {
|
|
225
|
+
reply = await this.handlePause(action.runId);
|
|
226
|
+
}
|
|
227
|
+
else if (action.action === "resume") {
|
|
228
|
+
reply = await this.handleResume(action.runId);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
// Unknown action — should not happen given the classifier union
|
|
232
|
+
reply = `Unrecognised action. For now, try /help for available commands.`;
|
|
233
|
+
}
|
|
234
|
+
// ── Weave completion notices ───────────────────────────────────────
|
|
235
|
+
if (completions.length > 0) {
|
|
236
|
+
const notices = completions
|
|
237
|
+
.map((c) => `[run ${c.runId ?? "unknown"} finished: ${c.phase}]`)
|
|
238
|
+
.join("\n");
|
|
239
|
+
reply = `${notices}\n\n${reply}`;
|
|
240
|
+
}
|
|
241
|
+
// Weave approval notices into LLM reply
|
|
242
|
+
if (approvalNotice) {
|
|
243
|
+
reply = `${approvalNotice}\n\n${reply}`;
|
|
244
|
+
}
|
|
245
|
+
// ── Persist ───────────────────────────────────────────────────────
|
|
246
|
+
const now = new Date().toISOString();
|
|
247
|
+
await this.store.append({ role: "user", content: input, ts: now });
|
|
248
|
+
await this.store.append({ role: "assistant", content: reply, ts: now });
|
|
249
|
+
return reply;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Stop a run by resolving it against the current disk roster, then calling
|
|
253
|
+
* RunSpawner.stop. Shared by /stop <runId> (deterministic slash path) and
|
|
254
|
+
* classifier steer:stop (natural-language path). Never reaches the LLM.
|
|
255
|
+
*/
|
|
256
|
+
async handleStop(runId) {
|
|
257
|
+
// Resolve against disk roster at stop-time (sc-4-7 — not from spawn-time memory)
|
|
258
|
+
const states = await this.roster.read();
|
|
259
|
+
const target = states.find((s) => s.runId === runId && s.status === "running");
|
|
260
|
+
if (!target)
|
|
261
|
+
return `No such running run: ${runId}`;
|
|
262
|
+
const result = await this.spawner.stop(runId, "Stopped via chat");
|
|
263
|
+
return result.killedPid !== undefined
|
|
264
|
+
? `Stopped run ${runId} (killed pid ${result.killedPid}).`
|
|
265
|
+
: `Stopped run ${runId} (no live process found; marked aborted).`;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Handle /careful [on|off].
|
|
269
|
+
* - "on" → set careful true, return confirmation
|
|
270
|
+
* - "off" → set careful false, return confirmation
|
|
271
|
+
* - undefined/other → report current state
|
|
272
|
+
*/
|
|
273
|
+
async handleCareful(arg) {
|
|
274
|
+
if (arg === "on") {
|
|
275
|
+
await this.carefulSidecar.setCareful(true);
|
|
276
|
+
return "Careful mode ON — new runs will pause at curated gates.";
|
|
277
|
+
}
|
|
278
|
+
else if (arg === "off") {
|
|
279
|
+
await this.carefulSidecar.setCareful(false);
|
|
280
|
+
return "Careful mode OFF — new runs will run in autopilot.";
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
const current = await this.carefulSidecar.isCareful();
|
|
284
|
+
return `Careful mode is currently ${current ? "ON" : "OFF"}. Use /careful on or /careful off to toggle.`;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Approve a pending checkpoint: guard with pendingExists, write the marker,
|
|
289
|
+
* clear the correlated RunState pending fields, and return an ack string.
|
|
290
|
+
* Returns a "no pending checkpoint" message and writes nothing if the pending
|
|
291
|
+
* file does not exist (sc-3-4).
|
|
292
|
+
*/
|
|
293
|
+
async handleApprove(checkpointId) {
|
|
294
|
+
if (!(await pendingExists(this.projectRoot, checkpointId))) {
|
|
295
|
+
return `No pending checkpoint found: ${checkpointId}`;
|
|
296
|
+
}
|
|
297
|
+
const marker = {
|
|
298
|
+
approvedAt: new Date().toISOString(),
|
|
299
|
+
approverId: resolveApprover(),
|
|
300
|
+
};
|
|
301
|
+
await saveApproved(this.projectRoot, checkpointId, marker);
|
|
302
|
+
await this.clearPending(checkpointId);
|
|
303
|
+
return `Approved checkpoint ${checkpointId}. The run will resume.`;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Reject a pending checkpoint: guard with pendingExists, write the marker
|
|
307
|
+
* carrying the feedback string, clear the correlated RunState, and return ack.
|
|
308
|
+
* Returns a "no pending checkpoint" message and writes nothing if absent (sc-3-4).
|
|
309
|
+
*/
|
|
310
|
+
async handleReject(checkpointId, feedback) {
|
|
311
|
+
if (!(await pendingExists(this.projectRoot, checkpointId))) {
|
|
312
|
+
return `No pending checkpoint found: ${checkpointId}`;
|
|
313
|
+
}
|
|
314
|
+
const marker = {
|
|
315
|
+
rejectedAt: new Date().toISOString(),
|
|
316
|
+
rejecterId: resolveApprover(),
|
|
317
|
+
feedback,
|
|
318
|
+
};
|
|
319
|
+
await saveRejected(this.projectRoot, checkpointId, marker);
|
|
320
|
+
await this.clearPending(checkpointId);
|
|
321
|
+
return `Rejected checkpoint ${checkpointId}. Feedback sent for rework.`;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Queue free-text guidance for a run at the next pipeline boundary.
|
|
325
|
+
* Shared by /tell <runId> <text> (deterministic slash path) and
|
|
326
|
+
* classifier tell (natural-language path). Never reaches the LLM.
|
|
327
|
+
*
|
|
328
|
+
* Guards: unknown run (not in roster) → clear error, writes nothing.
|
|
329
|
+
* Path-traversal: appendGuidance validates runId via safeSegment first.
|
|
330
|
+
* Does NOT require careful mode; guidance can be queued for any known run.
|
|
331
|
+
*/
|
|
332
|
+
async handleTell(runId, text) {
|
|
333
|
+
// Guard: check run exists in the roster (any status — not just running)
|
|
334
|
+
const exists = await hasRunDir(this.projectRoot, runId);
|
|
335
|
+
if (!exists) {
|
|
336
|
+
return `No such run: ${runId}`;
|
|
337
|
+
}
|
|
338
|
+
try {
|
|
339
|
+
await appendGuidance(this.projectRoot, runId, text);
|
|
340
|
+
}
|
|
341
|
+
catch (err) {
|
|
342
|
+
// Surface path-traversal or other appendGuidance errors clearly
|
|
343
|
+
return `Failed to queue guidance: ${err instanceof Error ? err.message : String(err)}`;
|
|
344
|
+
}
|
|
345
|
+
return `Queued guidance for run ${runId}.`;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Soft-pause a run at the next checkpoint boundary.
|
|
349
|
+
*
|
|
350
|
+
* Distinct from handleStop: this does NOT send a kill signal — the process
|
|
351
|
+
* stays alive and will hold at the next cooperative-pause gate in the pipeline.
|
|
352
|
+
*
|
|
353
|
+
* Guards: run must be found in the roster with status "running".
|
|
354
|
+
* Side effects: writes paused.json marker + flips chat-owned RunState to
|
|
355
|
+
* 'paused' (with pausedAt timestamp) via writeRunState.
|
|
356
|
+
*/
|
|
357
|
+
async handlePause(runId) {
|
|
358
|
+
const states = await this.roster.read();
|
|
359
|
+
const target = states.find((s) => s.runId === runId && s.status === "running");
|
|
360
|
+
if (!target)
|
|
361
|
+
return `No such running run: ${runId}`;
|
|
362
|
+
await setPaused(this.projectRoot, runId);
|
|
363
|
+
await writeRunState(this.projectRoot, {
|
|
364
|
+
...target,
|
|
365
|
+
status: "paused",
|
|
366
|
+
pausedAt: new Date().toISOString(),
|
|
367
|
+
});
|
|
368
|
+
return `Paused run ${runId} at the next boundary — the process stays alive (use /resume ${runId} to continue). This is NOT /stop.`;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Resume a soft-paused run.
|
|
372
|
+
*
|
|
373
|
+
* Clears the paused.json marker (best-effort) and flips RunState back
|
|
374
|
+
* to 'running' (dropping the pausedAt field). The pipeline's cooperative
|
|
375
|
+
* gate polls isPaused, so removing the marker allows the gate to advance.
|
|
376
|
+
*/
|
|
377
|
+
async handleResume(runId) {
|
|
378
|
+
await clearPaused(this.projectRoot, runId);
|
|
379
|
+
const states = await this.roster.read();
|
|
380
|
+
const target = states.find((s) => s.runId === runId && s.status === "paused");
|
|
381
|
+
if (target) {
|
|
382
|
+
// Destructure out pausedAt so it is NOT serialized back to disk.
|
|
383
|
+
const { pausedAt, ...rest } = target;
|
|
384
|
+
void pausedAt;
|
|
385
|
+
await writeRunState(this.projectRoot, { ...rest, status: "running" });
|
|
386
|
+
}
|
|
387
|
+
return `Resumed run ${runId}.`;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Clear pending fields from the RunState correlated to this checkpoint.
|
|
391
|
+
* Inverse of the Sprint 2 reflection block: finds the input-required RunState
|
|
392
|
+
* matching this checkpointId, drops the three pending fields, and sets
|
|
393
|
+
* status back to "running". Idempotent — no-op if no correlated state exists.
|
|
394
|
+
*/
|
|
395
|
+
async clearPending(checkpointId) {
|
|
396
|
+
const states = await this.roster.read();
|
|
397
|
+
const state = states.find((s) => s.status === "input-required" && s.pendingCheckpointId === checkpointId);
|
|
398
|
+
if (!state)
|
|
399
|
+
return;
|
|
400
|
+
// Destructure out the optional pending fields so they are NOT serialized.
|
|
401
|
+
const { pendingCheckpointId, pendingPrompt, pendingSince, ...rest } = state;
|
|
402
|
+
// Suppress unused-variable warnings — these are intentionally destructured out.
|
|
403
|
+
void pendingCheckpointId;
|
|
404
|
+
void pendingPrompt;
|
|
405
|
+
void pendingSince;
|
|
406
|
+
await writeRunState(this.projectRoot, { ...rest, status: "running" });
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Resolve a checkpoint id for NL approve/reject paths.
|
|
410
|
+
* - If an id is provided, use it directly.
|
|
411
|
+
* - If exactly one pending marker exists, use it.
|
|
412
|
+
* - If zero or multiple pending markers exist (without a named id), return
|
|
413
|
+
* an ambiguous result so the caller can ask the user instead of guessing.
|
|
414
|
+
*/
|
|
415
|
+
async resolveCheckpoint(id) {
|
|
416
|
+
if (id)
|
|
417
|
+
return { kind: "id", id };
|
|
418
|
+
const pending = await this.approvalReader.read();
|
|
419
|
+
if (pending.length === 1)
|
|
420
|
+
return { kind: "id", id: pending[0].checkpointId };
|
|
421
|
+
if (pending.length === 0) {
|
|
422
|
+
return { kind: "ambiguous", message: "No pending checkpoints to act on." };
|
|
423
|
+
}
|
|
424
|
+
const ids = pending.map((p) => p.checkpointId).join(", ");
|
|
425
|
+
return {
|
|
426
|
+
kind: "ambiguous",
|
|
427
|
+
message: `Multiple pending checkpoints — which one? ${ids}`,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Start an interactive REPL loop reading from stdin.
|
|
432
|
+
* Use handleTurn() directly in tests instead.
|
|
433
|
+
*/
|
|
434
|
+
async start() {
|
|
435
|
+
const rl = readline.createInterface({
|
|
436
|
+
input: process.stdin,
|
|
437
|
+
output: process.stdout,
|
|
438
|
+
terminal: false,
|
|
439
|
+
});
|
|
440
|
+
process.stdout.write("bober chat — type a question, /help for commands, /exit to quit\n> ");
|
|
441
|
+
// ── Sprint 5: seed project facts at chat startup (best-effort) ──
|
|
442
|
+
// A facts failure must NEVER break chat startup.
|
|
443
|
+
try {
|
|
444
|
+
await seedProjectFacts(this.projectRoot, this.memoryNamespace);
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
// Swallow silently — facts failure must never abort chat
|
|
448
|
+
}
|
|
449
|
+
for await (const line of rl) {
|
|
450
|
+
const input = line.trim();
|
|
451
|
+
if (!input) {
|
|
452
|
+
process.stdout.write("> ");
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
const reply = await this.handleTurn(input);
|
|
457
|
+
if (reply === null) {
|
|
458
|
+
process.stdout.write("Goodbye.\n");
|
|
459
|
+
rl.close();
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
process.stdout.write(`${reply}\n> `);
|
|
463
|
+
}
|
|
464
|
+
catch (err) {
|
|
465
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n> `);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
//# sourceMappingURL=chat-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-session.js","sourceRoot":"","sources":["../../src/chat/chat-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface CompletionEvent {
|
|
2
|
+
runId?: string;
|
|
3
|
+
phase: "complete" | "failed";
|
|
4
|
+
completed: number;
|
|
5
|
+
failed: number;
|
|
6
|
+
durationMs: number;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class CompletionTailer {
|
|
10
|
+
private readonly projectRoot;
|
|
11
|
+
private readonly store;
|
|
12
|
+
constructor(projectRoot: string, sessionId: string);
|
|
13
|
+
/**
|
|
14
|
+
* Poll .bober/history.jsonl for new pipeline-complete events since the last
|
|
15
|
+
* persisted byte cursor. Returns only newly-seen completions.
|
|
16
|
+
*
|
|
17
|
+
* Algorithm:
|
|
18
|
+
* 1. stat the file; ENOENT → return [].
|
|
19
|
+
* 2. If stat.size < cursor (rotation/shrink) → readFrom = 0.
|
|
20
|
+
* 3. Read bytes [readFrom, EOF) via Buffer slice.
|
|
21
|
+
* 4. Parse complete lines only (skip partial trailing line).
|
|
22
|
+
* 5. Filter for event === "pipeline-complete"; extract runId via marker.
|
|
23
|
+
* 6. Dedupe against seenRunIds; persist updated cursor + seenRunIds.
|
|
24
|
+
*/
|
|
25
|
+
poll(): Promise<CompletionEvent[]>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=completion-tailer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-tailer.d.ts","sourceRoot":"","sources":["../../src/chat/completion-tailer.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAoED,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAH9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;gBAGjB,WAAW,EAAE,MAAM,EACpC,SAAS,EAAE,MAAM;IAKnB;;;;;;;;;;;OAWG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;CA0GzC"}
|