@tokenfactory/acc-runner 0.38.3 → 0.39.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.
@@ -0,0 +1,101 @@
1
+ /**
2
+ * CC-1B (TURN-LANE): the companion claim loop.
3
+ *
4
+ * A COMPANION is a runner attached to one or more operator chats that serves
5
+ * their queued turns, distinct from a fleet runner draining the task lane
6
+ * (WORKSPACE_COMMAND_CHAT_CONTRACTS §2). This module is the chat-lane analogue of
7
+ * the batch `pump()` in watch.ts: it repeatedly claims queued turns across its
8
+ * conversations and drives each with `driveChatTurn`, subject to two guards that
9
+ * keep it from ever starving the code/review lanes:
10
+ *
11
+ * 1. MAX-SHARE — `computeChatClaimBudget` caps how many concurrency slots chat
12
+ * may hold (always leaving ≥1 for code/review), reading the batch lane's
13
+ * live in-flight count via the injected `activeCodeTasks()`.
14
+ * 2. CIRCUIT BREAKER — while the chat circuit is open (a `claude_exit_1`-class
15
+ * fault tripped it), the budget is 0 so no chat turn is claimed; the code
16
+ * lane is untouched.
17
+ *
18
+ * The loop owns per-turn `AbortController`s so an operator cancel (or runner
19
+ * shutdown) SIGTERMs the in-flight engine child and the driver requeues the turn
20
+ * cleanly — no duplicate completion. Everything (transport, engine, clock,
21
+ * active-task count, delegation minting) is injected, so the loop is exercised
22
+ * deterministically without a network or a `claude` binary.
23
+ */
24
+ import { type ChatLaneTransport, type ChatTurnDriveResult, type ClaimedChatTurn } from "./chat-lane.js";
25
+ import type { ChatCircuitBreaker } from "./runtime/chat-circuit-breaker.js";
26
+ import type { ConformantAgentEngine } from "./engines/types.js";
27
+ export interface ChatCompanionOptions {
28
+ /** This runner's id (claimant of turns). */
29
+ runnerId: string;
30
+ /** The chat-conformant engine driving replies. */
31
+ engine: ConformantAgentEngine;
32
+ /** The wire seam for claim/stream/complete/requeue. */
33
+ transport: ChatLaneTransport;
34
+ /** The chat-capability circuit breaker (shared with `doctor` / boot hydration). */
35
+ breaker: ChatCircuitBreaker;
36
+ /** Runner concurrency ceiling (shared with the batch lane). */
37
+ concurrencyLimit: number;
38
+ /** Chat-lane max share of that ceiling (0..1); ≥1 still reserves 1 code slot. */
39
+ maxShare: number;
40
+ /** Requested lease per claim (server clamps). */
41
+ leaseMs: number;
42
+ /** Conversations this companion currently serves (registration list). */
43
+ conversations: () => string[];
44
+ /** Live count of code/review tasks in flight on this runner (from watch.ts pump). */
45
+ activeCodeTasks: () => number;
46
+ /** Working directory forwarded to the engine per turn. */
47
+ cwd?: string;
48
+ /** Mint a per-turn delegation token (narrowly-scoped identity) — optional. */
49
+ mintDelegation?: (turn: ClaimedChatTurn) => Promise<string | undefined>;
50
+ /** Clock (test seam). */
51
+ now?: () => number;
52
+ /** Best-effort observability sink for terminal turn results. */
53
+ onResult?: (result: ChatTurnDriveResult) => void;
54
+ /** Best-effort log sink. */
55
+ onLog?: (line: string) => void;
56
+ }
57
+ /**
58
+ * The companion claim loop. Call `pumpOnce()` to claim + drive as many turns as
59
+ * the max-share budget currently allows (returns the turns launched this pump);
60
+ * `start()` schedules `pumpOnce` on an interval; `cancel(turnId)` aborts an
61
+ * in-flight turn (clean requeue); `stop()` aborts all in-flight turns.
62
+ */
63
+ export declare class ChatCompanion {
64
+ private readonly opts;
65
+ private readonly running;
66
+ private timer;
67
+ private stopped;
68
+ private rrCursor;
69
+ constructor(opts: ChatCompanionOptions);
70
+ /** Number of chat turns currently in flight on this companion. */
71
+ activeChatTurns(): number;
72
+ /** Turn ids currently in flight (stable snapshot). */
73
+ inFlightTurnIds(): string[];
74
+ /**
75
+ * The chat-lane claim budget right now: how many NEW turns may be claimed
76
+ * given concurrency, max-share, in-flight chat + code load, and the breaker.
77
+ */
78
+ budget(): number;
79
+ /**
80
+ * Claim + launch up to `budget()` turns across the served conversations,
81
+ * round-robin so no single busy conversation monopolises the budget. Returns
82
+ * the turns launched this pump (empty when the budget is 0 or every
83
+ * conversation's queue is empty).
84
+ */
85
+ pumpOnce(): Promise<ClaimedChatTurn[]>;
86
+ /** Start the periodic pump. `intervalMs` is the poll cadence between pumps. */
87
+ start(intervalMs?: number): void;
88
+ /**
89
+ * Abort one in-flight turn (operator cancel). The driver observes the signal,
90
+ * stops streaming, and requeues the turn — the "kill mid-stream ⇒ clean
91
+ * requeue, no dup side effects" path. Returns the settled result, or null when
92
+ * the turn is not in flight here.
93
+ */
94
+ cancel(turnId: string): Promise<ChatTurnDriveResult | null>;
95
+ /** Stop the loop: cancel the timer and abort every in-flight turn (requeue). */
96
+ stop(): Promise<ChatTurnDriveResult[]>;
97
+ private claim;
98
+ private launch;
99
+ private drive;
100
+ }
101
+ //# sourceMappingURL=chat-companion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-companion.d.ts","sourceRoot":"","sources":["../src/chat-companion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAE5E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,MAAM,EAAE,qBAAqB,CAAC;IAC9B,uDAAuD;IACvD,SAAS,EAAE,iBAAiB,CAAC;IAC7B,mFAAmF;IACnF,OAAO,EAAE,kBAAkB,CAAC;IAC5B,+DAA+D;IAC/D,gBAAgB,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,aAAa,EAAE,MAAM,MAAM,EAAE,CAAC;IAC9B,qFAAqF;IACrF,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACxE,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACjD,4BAA4B;IAC5B,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAQD;;;;;GAKG;AACH,qBAAa,aAAa;IAMZ,OAAO,CAAC,QAAQ,CAAC,IAAI;IALjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAK;gBAEQ,IAAI,EAAE,oBAAoB;IAEvD,kEAAkE;IAClE,eAAe,IAAI,MAAM;IAIzB,sDAAsD;IACtD,eAAe,IAAI,MAAM,EAAE;IAI3B;;;OAGG;IACH,MAAM,IAAI,MAAM;IAUhB;;;;;OAKG;IACG,QAAQ,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IA8B5C,+EAA+E;IAC/E,KAAK,CAAC,UAAU,SAAQ,GAAG,IAAI;IAS/B;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAOjE,gFAAgF;IAC1E,IAAI,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;YAW9B,KAAK;IAiBnB,OAAO,CAAC,MAAM;YAWA,KAAK;CAwBpB"}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * CC-1B (TURN-LANE): the companion claim loop.
3
+ *
4
+ * A COMPANION is a runner attached to one or more operator chats that serves
5
+ * their queued turns, distinct from a fleet runner draining the task lane
6
+ * (WORKSPACE_COMMAND_CHAT_CONTRACTS §2). This module is the chat-lane analogue of
7
+ * the batch `pump()` in watch.ts: it repeatedly claims queued turns across its
8
+ * conversations and drives each with `driveChatTurn`, subject to two guards that
9
+ * keep it from ever starving the code/review lanes:
10
+ *
11
+ * 1. MAX-SHARE — `computeChatClaimBudget` caps how many concurrency slots chat
12
+ * may hold (always leaving ≥1 for code/review), reading the batch lane's
13
+ * live in-flight count via the injected `activeCodeTasks()`.
14
+ * 2. CIRCUIT BREAKER — while the chat circuit is open (a `claude_exit_1`-class
15
+ * fault tripped it), the budget is 0 so no chat turn is claimed; the code
16
+ * lane is untouched.
17
+ *
18
+ * The loop owns per-turn `AbortController`s so an operator cancel (or runner
19
+ * shutdown) SIGTERMs the in-flight engine child and the driver requeues the turn
20
+ * cleanly — no duplicate completion. Everything (transport, engine, clock,
21
+ * active-task count, delegation minting) is injected, so the loop is exercised
22
+ * deterministically without a network or a `claude` binary.
23
+ */
24
+ import { computeChatClaimBudget, driveChatTurn, } from "./chat-lane.js";
25
+ /**
26
+ * The companion claim loop. Call `pumpOnce()` to claim + drive as many turns as
27
+ * the max-share budget currently allows (returns the turns launched this pump);
28
+ * `start()` schedules `pumpOnce` on an interval; `cancel(turnId)` aborts an
29
+ * in-flight turn (clean requeue); `stop()` aborts all in-flight turns.
30
+ */
31
+ export class ChatCompanion {
32
+ opts;
33
+ running = new Map();
34
+ timer = null;
35
+ stopped = false;
36
+ rrCursor = 0;
37
+ constructor(opts) {
38
+ this.opts = opts;
39
+ }
40
+ /** Number of chat turns currently in flight on this companion. */
41
+ activeChatTurns() {
42
+ return this.running.size;
43
+ }
44
+ /** Turn ids currently in flight (stable snapshot). */
45
+ inFlightTurnIds() {
46
+ return [...this.running.keys()];
47
+ }
48
+ /**
49
+ * The chat-lane claim budget right now: how many NEW turns may be claimed
50
+ * given concurrency, max-share, in-flight chat + code load, and the breaker.
51
+ */
52
+ budget() {
53
+ return computeChatClaimBudget({
54
+ concurrencyLimit: this.opts.concurrencyLimit,
55
+ maxShare: this.opts.maxShare,
56
+ activeChatTurns: this.running.size,
57
+ activeCodeTasks: this.opts.activeCodeTasks(),
58
+ circuitOpen: this.opts.breaker.isOpen(),
59
+ });
60
+ }
61
+ /**
62
+ * Claim + launch up to `budget()` turns across the served conversations,
63
+ * round-robin so no single busy conversation monopolises the budget. Returns
64
+ * the turns launched this pump (empty when the budget is 0 or every
65
+ * conversation's queue is empty).
66
+ */
67
+ async pumpOnce() {
68
+ if (this.stopped)
69
+ return [];
70
+ const launched = [];
71
+ let budget = this.budget();
72
+ if (budget <= 0)
73
+ return launched;
74
+ const convos = this.opts.conversations();
75
+ if (convos.length === 0)
76
+ return launched;
77
+ // Round-robin start point rotates each pump so a claim-empty conversation
78
+ // does not always shadow the ones after it.
79
+ let attemptsWithoutClaim = 0;
80
+ let idx = this.rrCursor % convos.length;
81
+ while (budget > 0 && attemptsWithoutClaim < convos.length) {
82
+ const conversationId = convos[idx % convos.length];
83
+ idx += 1;
84
+ const turn = await this.claim(conversationId);
85
+ if (!turn) {
86
+ attemptsWithoutClaim += 1;
87
+ continue;
88
+ }
89
+ attemptsWithoutClaim = 0;
90
+ budget -= 1;
91
+ launched.push(turn);
92
+ this.launch(turn);
93
+ }
94
+ this.rrCursor = idx % Math.max(1, convos.length);
95
+ return launched;
96
+ }
97
+ /** Start the periodic pump. `intervalMs` is the poll cadence between pumps. */
98
+ start(intervalMs = 1_000) {
99
+ if (this.timer)
100
+ return;
101
+ this.timer = setInterval(() => {
102
+ void this.pumpOnce();
103
+ }, intervalMs);
104
+ this.timer.unref?.();
105
+ void this.pumpOnce();
106
+ }
107
+ /**
108
+ * Abort one in-flight turn (operator cancel). The driver observes the signal,
109
+ * stops streaming, and requeues the turn — the "kill mid-stream ⇒ clean
110
+ * requeue, no dup side effects" path. Returns the settled result, or null when
111
+ * the turn is not in flight here.
112
+ */
113
+ async cancel(turnId) {
114
+ const rt = this.running.get(turnId);
115
+ if (!rt)
116
+ return null;
117
+ rt.controller.abort();
118
+ return rt.done;
119
+ }
120
+ /** Stop the loop: cancel the timer and abort every in-flight turn (requeue). */
121
+ async stop() {
122
+ this.stopped = true;
123
+ if (this.timer) {
124
+ clearInterval(this.timer);
125
+ this.timer = null;
126
+ }
127
+ const pending = [...this.running.values()];
128
+ for (const rt of pending)
129
+ rt.controller.abort();
130
+ return Promise.all(pending.map((rt) => rt.done));
131
+ }
132
+ async claim(conversationId) {
133
+ try {
134
+ return await this.opts.transport.claim({
135
+ conversationId,
136
+ runnerId: this.opts.runnerId,
137
+ engineId: this.opts.engine.id,
138
+ tier: this.opts.engine.capabilities.tier,
139
+ leaseMs: this.opts.leaseMs,
140
+ });
141
+ }
142
+ catch (err) {
143
+ this.opts.onLog?.(`[acc-runner] chat claim(${conversationId}) failed: ${err.message}`);
144
+ return null;
145
+ }
146
+ }
147
+ launch(turn) {
148
+ const controller = new AbortController();
149
+ const done = this.drive(turn, controller.signal).finally(() => {
150
+ this.running.delete(turn.id);
151
+ // Freed a slot — re-pump so a queued turn (or a requeued one) is picked up
152
+ // immediately rather than waiting for the next interval tick.
153
+ if (!this.stopped)
154
+ void this.pumpOnce();
155
+ });
156
+ this.running.set(turn.id, { turn, controller, done });
157
+ }
158
+ async drive(turn, signal) {
159
+ const delegationToken = this.opts.mintDelegation
160
+ ? await this.opts.mintDelegation(turn).catch(() => undefined)
161
+ : undefined;
162
+ const result = await driveChatTurn(turn, {
163
+ engine: this.opts.engine,
164
+ transport: this.opts.transport,
165
+ signal,
166
+ ...(this.opts.cwd !== undefined ? { cwd: this.opts.cwd } : {}),
167
+ ...(delegationToken !== undefined ? { delegationToken } : {}),
168
+ ...(this.opts.now ? { now: this.opts.now } : {}),
169
+ onCircuitTrip: async (info) => {
170
+ await this.opts.breaker.trip({
171
+ cause: info.cause,
172
+ turnId: turn.id,
173
+ conversationId: turn.conversation_id,
174
+ detail: info.detail,
175
+ ...(this.opts.now ? { now: this.opts.now } : {}),
176
+ });
177
+ },
178
+ });
179
+ this.opts.onResult?.(result);
180
+ return result;
181
+ }
182
+ }
183
+ //# sourceMappingURL=chat-companion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-companion.js","sourceRoot":"","sources":["../src/chat-companion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,286 @@
1
+ /**
2
+ * CC-1B (TURN-LANE): the runner-side chat claim lane + turn lifecycle.
3
+ *
4
+ * The chat lane is a SECOND lane beside the batch task/review lanes
5
+ * (docs/acc/WORKSPACE_COMMAND_CHAT_CONTRACTS.md §1). A *turn* is one operator
6
+ * prompt → one streamed agent reply. Turns are queued server-side; a companion
7
+ * runner CLAIMS a queued turn under a time-boxed lease (acc.claim_chat_turn,
8
+ * advisory-lock per conversation — migration 0254), STREAMS the reply as deltas,
9
+ * and COMPLETES it — or REQUEUES it when it loses the lease/capacity, so another
10
+ * companion finishes the turn without burning an operator turn.
11
+ *
12
+ * This module owns:
13
+ * 1. The turn LIFECYCLE state machine (queued → claimed → streaming →
14
+ * awaiting_confirmation → done | capacity_paused | failed | cancelled),
15
+ * with a transition validator.
16
+ * 2. The failure → disposition mapping: infra failures REQUEUE (never burn a
17
+ * turn); `claude_exit_1`-class failures open the chat circuit breaker AND
18
+ * requeue; a genuine agent error COMPLETES the turn as `error`.
19
+ * 3. `driveChatTurn` — the per-turn driver, an engine-agnostic loop over a
20
+ * `ConformantAgentEngine.streamTurn` that emits exactly ONE terminal
21
+ * transport call (complete OR requeue) so an abort mid-stream produces a
22
+ * clean requeue with no duplicate side effects.
23
+ * 4. `computeChatClaimBudget` — the chat-lane max-share knob so chat turns can
24
+ * never starve the code/review lanes of concurrency slots.
25
+ *
26
+ * Every side effect is behind the injectable `ChatLaneTransport` + the engine +
27
+ * an optional abort signal, so the whole lifecycle is exercised deterministically
28
+ * (tests/unit/chat-lane*.test.ts) with no `claude` binary and no network.
29
+ */
30
+ import { type ClaudeExitClass, type ClassifiedExit } from "./failure-classifier.js";
31
+ import type { ConformantAgentEngine, EngineCapabilityTier } from "./engines/types.js";
32
+ /** Chat-lane protocol version (mirrors the web-app constant of the same name). */
33
+ export declare const CHAT_LANE_PROTOCOL_VERSION: 1;
34
+ /** Terminal disposition of a completed turn (mirror of ChatTurnOutcome). */
35
+ export type ChatTurnOutcome = "ok" | "error" | "cancelled";
36
+ /** Why a turn was returned to the queue instead of completed. */
37
+ export type ChatTurnRequeueReason = "lease_expired" | "capacity_lost" | "engine_unavailable" | "credential_lost" | "operator_cancelled" | "runner_shutdown";
38
+ /** runner → server: one streamed delta of the assistant turn's output. */
39
+ export interface ChatTurnStreamPayload {
40
+ seq: number;
41
+ delta: string;
42
+ done: boolean;
43
+ }
44
+ /** runner → server: the turn reached a terminal state. */
45
+ export interface ChatTurnCompletePayload {
46
+ outcome: ChatTurnOutcome;
47
+ total_seq: number;
48
+ error?: string;
49
+ /**
50
+ * Additive to the wire complete payload: true when the reply proposes an
51
+ * action the operator must confirm before it applies. The turn still
52
+ * completes `ok` (the reply streamed fine); the pending confirmation lives in
53
+ * acc.proposed_actions. A pre-CC-1B consumer ignores this field.
54
+ */
55
+ awaiting_confirmation?: boolean;
56
+ }
57
+ /** server ↔ runner: return the turn to the queue for another claimant. */
58
+ export interface ChatTurnRequeuePayload {
59
+ reason: ChatTurnRequeueReason;
60
+ requeue_count: number;
61
+ }
62
+ /**
63
+ * A turn as claimed from acc.claim_chat_turn (the columns the driver needs).
64
+ * Mirrors the acc.chat_turns row the RPC returns.
65
+ */
66
+ export interface ClaimedChatTurn {
67
+ id: string;
68
+ conversation_id: string;
69
+ org_id: string;
70
+ turn_ordinal: number | null;
71
+ prompt: string;
72
+ tier: EngineCapabilityTier;
73
+ engine_id: string;
74
+ runner_id: string;
75
+ requeue_count: number;
76
+ lease_expires_at: string | null;
77
+ }
78
+ /**
79
+ * The runner-side turn lifecycle. A superset of the acc.chat_turns DB status
80
+ * enum: `awaiting_confirmation` and `capacity_paused` are RUNNER phases (the DB
81
+ * has no such status — a confirmation-pending turn is still `done` at the DB
82
+ * with a proposed_actions row; a capacity-paused turn is `requeued`). Modeling
83
+ * them here lets the driver + companion report the full operator-visible
84
+ * lifecycle without a migration.
85
+ */
86
+ export type ChatTurnLifecycle = "queued" | "claimed" | "streaming" | "awaiting_confirmation" | "done" | "capacity_paused" | "failed" | "cancelled" | "requeued";
87
+ /** Terminal lifecycle states — no further transition is valid from these. */
88
+ export declare const TERMINAL_CHAT_LIFECYCLE: readonly ChatTurnLifecycle[];
89
+ /** True when `to` is a legal next lifecycle state from `from`. */
90
+ export declare function isValidChatTransition(from: ChatTurnLifecycle, to: ChatTurnLifecycle): boolean;
91
+ /** True when the lifecycle state is terminal (the turn is settled). */
92
+ export declare function isTerminalChatLifecycle(state: ChatTurnLifecycle): boolean;
93
+ /**
94
+ * What the driver does with a failed turn:
95
+ * - `requeue` — an infra failure (recoverable capacity / transient
96
+ * engine unavailability). The turn goes back to the
97
+ * queue; NO operator turn is burned, the chat circuit
98
+ * stays closed.
99
+ * - `quarantine_requeue` — a `claude_exit_1`-class fault (broken credential /
100
+ * host / hard billing wall). OPEN the chat circuit
101
+ * breaker AND requeue the turn (survives on another
102
+ * companion) — but this runner stops claiming chat.
103
+ * - `error` — a genuine agent/task error. COMPLETE the turn as
104
+ * `error`; the operator turn IS spent (a real reply
105
+ * failure, not infra), so it must not silently loop.
106
+ */
107
+ export type ChatFailureDisposition = {
108
+ action: "requeue";
109
+ reason: ChatTurnRequeueReason;
110
+ quarantine: false;
111
+ detail: string;
112
+ } | {
113
+ action: "quarantine_requeue";
114
+ reason: ChatTurnRequeueReason;
115
+ cause: ClaudeExitClass;
116
+ detail: string;
117
+ } | {
118
+ action: "error";
119
+ detail: string;
120
+ };
121
+ /**
122
+ * Map a shared-taxonomy `ClassifiedExit` onto a chat-lane disposition. The split
123
+ * mirrors the batch lane's machine-vs-task rule but reroutes the terminal action
124
+ * to the chat lane's requeue/circuit model:
125
+ *
126
+ * capacity_exhausted | subscription_exhausted → requeue (capacity_lost) [infra]
127
+ * claude_unavailable (transient) → requeue (engine_unavailable) [infra]
128
+ * auth_expired → quarantine_requeue (credential_lost)
129
+ * env_broken → quarantine_requeue (engine_unavailable)
130
+ * usage_limit (hard wall) → quarantine_requeue (capacity_lost)
131
+ * task_error → error (turn completes 'error')
132
+ */
133
+ export declare function classifyChatDisposition(classified: ClassifiedExit): ChatFailureDisposition;
134
+ /**
135
+ * The chat-lane wire seam. Claim goes through the service-role acc.claim_chat_turn
136
+ * RPC (advisory-lock per conversation); stream/complete/requeue carry the
137
+ * lifecycle messages. Behind this interface a production adapter broadcasts on
138
+ * `chat:<conversation_id>` and/or posts to the control-plane API; the driver
139
+ * neither knows nor cares, so tests inject a recording fake.
140
+ */
141
+ export interface ChatLaneTransport {
142
+ /** Claim the oldest queued turn on a conversation, or null when the queue is empty. */
143
+ claim(args: {
144
+ conversationId: string;
145
+ runnerId: string;
146
+ engineId: string;
147
+ tier: EngineCapabilityTier;
148
+ leaseMs: number;
149
+ }): Promise<ClaimedChatTurn | null>;
150
+ /** Mark a claimed turn as streaming (claimed → streaming). */
151
+ markStreaming?(turn: ClaimedChatTurn): Promise<void>;
152
+ /** Emit one streamed delta for a turn. */
153
+ stream(turn: ClaimedChatTurn, payload: ChatTurnStreamPayload): Promise<void>;
154
+ /** Terminally complete a turn (ok | error | cancelled). */
155
+ complete(turn: ClaimedChatTurn, payload: ChatTurnCompletePayload): Promise<void>;
156
+ /** Return a turn to the queue for another claimant. */
157
+ requeue(turn: ClaimedChatTurn, payload: ChatTurnRequeuePayload): Promise<void>;
158
+ }
159
+ export interface DriveChatTurnDeps {
160
+ /** The chat-conformant engine that streams the reply. */
161
+ engine: ConformantAgentEngine;
162
+ /** The wire seam for stream/complete/requeue. */
163
+ transport: ChatLaneTransport;
164
+ /** Working directory forwarded to the engine (repo checkout for the turn). */
165
+ cwd?: string;
166
+ /** Per-turn delegation Bearer token forwarded to the acc-mcp bus. */
167
+ delegationToken?: string;
168
+ /** Abort signal; aborting mid-stream produces a clean requeue (no dup complete). */
169
+ signal?: AbortSignal;
170
+ /** Requeue reason to use when the turn is aborted (default operator_cancelled). */
171
+ abortReason?: ChatTurnRequeueReason;
172
+ /**
173
+ * Decide whether the fully-streamed reply proposes an action needing operator
174
+ * confirmation (→ awaiting_confirmation). Default: never (no confirmation).
175
+ */
176
+ requiresConfirmation?: (fullText: string, turn: ClaimedChatTurn) => boolean;
177
+ /**
178
+ * Detect a SILENT engine failure: a clean stream that produced zero visible
179
+ * text. Mirrors the batch lane's `claude_unavailable → health probe` rule —
180
+ * if the probe says the host/binary is broken, the empty turn is really an
181
+ * env_broken fault (→ quarantine_requeue) rather than a genuine empty reply.
182
+ * Default: treat an empty reply as a real (`ok`) empty reply.
183
+ */
184
+ silentFailureProbe?: () => Promise<ClassifiedExit | null>;
185
+ /** Clock (test seam). */
186
+ now?: () => number;
187
+ /** Called when the driver opens the chat circuit (companion trips its breaker). */
188
+ onCircuitTrip?: (info: {
189
+ cause: ClaudeExitClass;
190
+ detail: string;
191
+ }) => Promise<void> | void;
192
+ /** Best-effort structured log sink. */
193
+ onEvent?: (event: ChatTurnDriveEvent) => void;
194
+ }
195
+ /** A structured lifecycle event emitted by the driver (observability seam). */
196
+ export interface ChatTurnDriveEvent {
197
+ turnId: string;
198
+ conversationId: string;
199
+ lifecycle: ChatTurnLifecycle;
200
+ detail?: string;
201
+ }
202
+ /** The terminal result of driving one turn. */
203
+ export interface ChatTurnDriveResult {
204
+ turnId: string;
205
+ conversationId: string;
206
+ /** The terminal lifecycle state the turn settled in. */
207
+ lifecycle: Extract<ChatTurnLifecycle, "done" | "awaiting_confirmation" | "failed" | "cancelled" | "requeued" | "capacity_paused">;
208
+ /** Present when the turn was completed (done/awaiting_confirmation/failed). */
209
+ outcome?: ChatTurnOutcome;
210
+ /** Present when the turn was requeued. */
211
+ requeueReason?: ChatTurnRequeueReason;
212
+ /** Total deltas emitted (for consumer gap detection). */
213
+ totalSeq: number;
214
+ /** True when driving this turn opened the chat circuit breaker. */
215
+ quarantined: boolean;
216
+ /** Human-readable detail (error/requeue reason). */
217
+ detail?: string;
218
+ }
219
+ /**
220
+ * Drive one claimed turn to a terminal state. Emits EXACTLY ONE terminal
221
+ * transport call (complete OR requeue), guarded by `settled`, so a mid-stream
222
+ * abort/failure can never both requeue AND complete the same turn — the
223
+ * "kill mid-stream ⇒ clean requeue, no dup side effects" invariant.
224
+ */
225
+ export declare function driveChatTurn(turn: ClaimedChatTurn, deps: DriveChatTurnDeps): Promise<ChatTurnDriveResult>;
226
+ /** Env var carrying the chat-lane max-share fraction (0..1). */
227
+ export declare const CHAT_MAX_SHARE_ENV = "ACC_RUNNER_CHAT_MAX_SHARE";
228
+ /** Default chat-lane max share of runner concurrency. */
229
+ export declare const DEFAULT_CHAT_MAX_SHARE = 0.5;
230
+ /**
231
+ * Resolve the chat-lane max-share fraction from a raw env value. Blank/absent ⇒
232
+ * default; a value ≤0 disables chat claiming; a value ≥1 is clamped so at least
233
+ * one slot always remains for the code/review lanes (chat can never take the
234
+ * whole runner). Non-numeric ⇒ default (a typo must not starve either lane).
235
+ */
236
+ export declare function resolveChatMaxShare(raw: string | undefined | null): number;
237
+ /**
238
+ * Compute how many NEW chat turns the runner may claim right now, given its
239
+ * concurrency ceiling and current mixed load. The max-share invariant guarantees
240
+ * the code/review lanes never starve:
241
+ *
242
+ * chatCeiling = clamp(floor(concurrency * maxShare), 0, concurrency - 1)
243
+ *
244
+ * i.e. chat may occupy at most `chatCeiling` slots, and that ceiling is capped at
245
+ * `concurrency - 1` so at least one slot is ALWAYS reservable for a code/review
246
+ * task even at maxShare = 1. The live budget then subtracts the chat turns
247
+ * already in flight and is further bounded by the runner's actual free capacity
248
+ * (concurrency − everything running). Returns 0 while the chat circuit is open or
249
+ * chat is disabled (maxShare ≤ 0).
250
+ */
251
+ export declare function computeChatClaimBudget(opts: {
252
+ concurrencyLimit: number;
253
+ maxShare: number;
254
+ activeChatTurns: number;
255
+ activeCodeTasks: number;
256
+ circuitOpen?: boolean;
257
+ }): number;
258
+ /** Env var that opts the runner into the chat lane (a companion). */
259
+ export declare const CHAT_LANE_ENABLED_ENV = "ACC_RUNNER_CHAT_LANE";
260
+ /** Env var carrying the requested per-turn lease (ms). */
261
+ export declare const CHAT_LEASE_MS_ENV = "ACC_RUNNER_CHAT_LEASE_MS";
262
+ /** Default per-turn lease; mirrors acc.claim_chat_turn's default (60s). */
263
+ export declare const DEFAULT_CHAT_LEASE_MS = 60000;
264
+ /**
265
+ * Resolve the requested per-turn lease. Blank/absent/non-numeric ⇒ default;
266
+ * numeric values clamp to the RPC's own accepted window (1s..10m) so the runner
267
+ * never asks for a lease the server would silently clamp anyway.
268
+ */
269
+ export declare function resolveChatLeaseMs(raw: string | undefined | null): number;
270
+ /** The resolved chat-lane knobs (companion enablement + share + lease). */
271
+ export interface ChatLaneRunnerConfig {
272
+ /** Whether this runner serves the chat lane at all. */
273
+ enabled: boolean;
274
+ /** Chat-lane max share of runner concurrency (0..1). */
275
+ maxShare: number;
276
+ /** Requested per-turn lease (ms). */
277
+ leaseMs: number;
278
+ }
279
+ /**
280
+ * Resolve the chat-lane knobs from the environment in ONE place so the companion
281
+ * loop and any caps/telemetry read the same values. A share of 0 (or the flag
282
+ * absent) means the runner does not claim chat turns even when enabled — the
283
+ * code/review lanes keep the whole runner.
284
+ */
285
+ export declare function resolveChatLaneConfig(env?: NodeJS.ProcessEnv): ChatLaneRunnerConfig;
286
+ //# sourceMappingURL=chat-lane.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-lane.d.ts","sourceRoot":"","sources":["../src/chat-lane.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAsB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAExG,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EAErB,MAAM,oBAAoB,CAAC;AAW5B,kFAAkF;AAClF,eAAO,MAAM,0BAA0B,EAAG,CAAU,CAAC;AAErD,4EAA4E;AAC5E,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,OAAO,GAAG,WAAW,CAAC;AAE3D,iEAAiE;AACjE,MAAM,MAAM,qBAAqB,GAC7B,eAAe,GACf,eAAe,GACf,oBAAoB,GACpB,iBAAiB,GACjB,oBAAoB,GACpB,iBAAiB,CAAC;AAEtB,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED,0DAA0D;AAC1D,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,0EAA0E;AAC1E,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,oBAAoB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAMD;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,SAAS,GACT,WAAW,GACX,uBAAuB,GACvB,MAAM,GACN,iBAAiB,GACjB,QAAQ,GACR,WAAW,GACX,UAAU,CAAC;AAEf,6EAA6E;AAC7E,eAAO,MAAM,uBAAuB,EAAE,SAAS,iBAAiB,EAM/D,CAAC;AAqBF,kEAAkE;AAClE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,iBAAiB,GAAG,OAAO,CAE7F;AAED,uEAAuE;AACvE,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAEzE;AAMD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,sBAAsB,GAC9B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,UAAU,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvF;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,cAAc,GAAG,sBAAsB,CAoB1F;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,uFAAuF;IACvF,KAAK,CAAC,IAAI,EAAE;QACV,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,oBAAoB,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAEpC,8DAA8D;IAC9D,aAAa,CAAC,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErD,0CAA0C;IAC1C,MAAM,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7E,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjF,uDAAuD;IACvD,OAAO,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAMD,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,MAAM,EAAE,qBAAqB,CAAC;IAC9B,iDAAiD;IACjD,SAAS,EAAE,iBAAiB,CAAC;IAC7B,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,mFAAmF;IACnF,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,KAAK,OAAO,CAAC;IAC5E;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC1D,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,mFAAmF;IACnF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3F,uCAAuC;IACvC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/C;AAED,+EAA+E;AAC/E,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,SAAS,EAAE,OAAO,CAChB,iBAAiB,EACjB,MAAM,GAAG,uBAAuB,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,iBAAiB,CAC3F,CAAC;IACF,+EAA+E;IAC/E,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,0CAA0C;IAC1C,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,WAAW,EAAE,OAAO,CAAC;IACrB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAwBD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,eAAe,EACrB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAqH9B;AAMD,gEAAgE;AAChE,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAC9D,yDAAyD;AACzD,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAQ1E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,MAAM,CAeT;AAMD,qEAAqE;AACrE,eAAO,MAAM,qBAAqB,yBAAyB,CAAC;AAC5D,0DAA0D;AAC1D,eAAO,MAAM,iBAAiB,6BAA6B,CAAC;AAC5D,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAQ5C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAIzE;AAED,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,oBAAoB,CAOhG"}