@rallycry/conveyor-agent 6.4.1 → 7.0.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/dist/index.d.ts CHANGED
@@ -1,296 +1,272 @@
1
1
  import * as _project_shared from '@project/shared';
2
- import { AgentRunnerStatus, MultimodalBlock, ProjectEnvironmentStatus, ChatMessageResponse, TaskFileResponse, TaskContext, AgentEvent, AgentQuestion, IncomingMessagePayload, SetModePayload, AgentMode, SubtaskCreatePayload, SubtaskUpdateFields, SubtaskResponse, StartChildCloudBuildResponse, TaskLookupResponse, UpdateTaskPropertiesPayload, IconListItem, GenerateIconResponse, TaskPropertiesResponse, TriggerIdentificationResponse, ModeTransitionPayload, DebugSessionState, DebugSessionSummary, IncidentDTO, TaskIncidentDTO, ResourceTierName, ScaleUpResponse, TaskDependencySummary, QueryGcpLogsResponse, TagAuditRunnerRequest, TagAuditRunnerResponse, TagAuditProgressActivity, DebugTelemetryEvent } from '@project/shared';
3
- export { AgentEvent, ChatMessage, DebugBreakpointHit, DebugModeEvent, TaskContext, TaskFileContext } from '@project/shared';
2
+ import { AgentSessionServiceMethods, AgentMode, AgentQuestion, AgentRunnerStatus, DebugTelemetryEvent, DebugSessionSummary } from '@project/shared';
3
+ export * from '@project/shared';
4
4
  import { ChildProcess } from 'node:child_process';
5
5
 
6
- /**
7
- * Harness-neutral types for agent query execution.
8
- *
9
- * These types abstract the underlying agent SDK so that the runner,
10
- * execution, and tool layers never reference SDK-specific imports
11
- * directly. The only place that should import from
12
- * `@anthropic-ai/claude-agent-sdk` is `harness/claude-code/`.
13
- */
14
-
15
- interface HarnessUserMessage {
16
- type: "user";
17
- session_id: string;
18
- message: {
19
- role: "user";
20
- content: string | unknown[];
21
- };
22
- parent_tool_use_id: null;
6
+ interface ModelUsageEntry {
7
+ model: string;
8
+ inputTokens: number;
9
+ outputTokens: number;
10
+ cacheReadInputTokens: number;
11
+ cacheCreationInputTokens: number;
12
+ costUSD: number;
23
13
  }
24
14
 
25
- interface AgentRunnerConfig {
26
- conveyorApiUrl: string;
15
+ interface AgentConnectionConfig {
16
+ apiUrl: string;
27
17
  taskToken: string;
28
- taskId: string;
29
- model: string;
30
- instructions: string;
31
- workspaceDir: string;
32
- mode?: _project_shared.RunnerMode;
33
- isAuto?: boolean;
34
- agentSettings?: _project_shared.AgentSettings;
18
+ sessionId: string;
19
+ runnerMode?: "task" | "pm" | "code-review";
35
20
  }
36
- interface AgentRunnerCallbacks {
37
- onEvent: (event: _project_shared.AgentEvent) => void | Promise<void>;
38
- onStatusChange: (status: _project_shared.AgentRunnerStatus) => void | Promise<void>;
21
+ interface IncomingMessage {
22
+ content: string;
23
+ userId: string;
24
+ files?: Array<{
25
+ name: string;
26
+ content: string;
27
+ mimeType?: string;
28
+ }>;
39
29
  }
40
-
41
- declare class AgentRunner {
42
- private config;
43
- private connection;
44
- private callbacks;
45
- private _state;
46
- private stopped;
47
- private interrupted;
48
- private inputResolver;
49
- private pendingMessages;
50
- private setupLog;
51
- private heartbeatTimer;
52
- private taskContext;
53
- private planSync;
54
- private costTracker;
55
- private worktreeActive;
56
- private agentMode;
57
- private hasExitedPlanMode;
58
- private pendingModeRestart;
59
- private pendingModeAutoStart;
60
- private sessionIds;
61
- private lastQueryModeRestart;
62
- private startCommandStarted;
63
- private prNudgeCount;
64
- private idleTimer;
65
- private idleCheckInterval;
66
- private conveyorConfig;
67
- private _queryHost;
68
- private tunnelClient;
69
- private harness;
70
- constructor(config: AgentRunnerConfig, callbacks: AgentRunnerCallbacks);
71
- get state(): AgentRunnerStatus;
72
- private get effectiveAgentMode();
73
- private setState;
74
- private startHeartbeat;
75
- private stopHeartbeat;
76
- private clearIdleTimers;
77
- start(): Promise<void>;
78
- private tryInitWorktree;
79
- private fetchAndInitContext;
80
- private tryPostContextWorktree;
81
- private startPreviewTunnel;
82
- private activateWorktree;
83
- private checkoutWorktreeBranch;
84
- private needsPRNudge;
85
- private maybeSendPRNudge;
86
- private sendPRNudgeQuery;
87
- private executeInitialMode;
88
- private runQuerySafe;
89
- private handleModeRestartCycle;
90
- private runCoreLoop;
91
- private handleRunStartCommand;
92
- private logEffectiveSettings;
93
- private injectHumanMessage;
94
- private waitForMessage;
95
- private waitForUserContent;
96
- createInputStream(initialPrompt: string | MultimodalBlock[]): AsyncGenerator<HarnessUserMessage, void, unknown>;
97
- private asQueryHost;
98
- private lastAnnouncedMode;
99
- private handleModeChange;
100
- private updateExitedPlanModeFlag;
101
- softStop(): void;
102
- stop(): void;
30
+ interface SetModeData {
31
+ agentMode: AgentMode;
103
32
  }
104
-
105
- interface ProjectRunnerConfig {
106
- conveyorApiUrl: string;
107
- projectToken: string;
108
- projectId: string;
109
- projectDir: string;
33
+ interface ApiKeyUpdateData {
34
+ apiKey: string;
35
+ isSubscription?: boolean;
110
36
  }
111
- declare class ProjectRunner {
112
- private connection;
113
- private projectDir;
114
- private activeAgents;
115
- private heartbeatTimer;
116
- private stopping;
117
- private resolveLifecycle;
118
- private chatSessionIds;
119
- private startCommandChild;
120
- private startCommandRunning;
121
- private setupComplete;
122
- private branchSwitchCommand;
123
- private commitWatcher;
124
- constructor(config: ProjectRunnerConfig);
125
- private checkoutWorkspaceBranch;
126
- private executeSetupCommand;
127
- private executeStartCommand;
128
- killStartCommand(): Promise<void>;
129
- restartStartCommand(): Promise<void>;
130
- getEnvironmentStatus(): ProjectEnvironmentStatus;
131
- private getCurrentBranch;
132
- private smartSync;
133
- private handleSwitchBranch;
134
- private handleSyncEnvironment;
135
- private handleGetEnvStatus;
136
- start(): Promise<void>;
137
- private setupSignalHandlers;
138
- private handleAssignment;
139
- private handleStopTask;
140
- stop(): Promise<void>;
141
- }
142
-
143
- declare class ConveyorConnection {
37
+ declare class AgentConnection {
144
38
  private socket;
145
- private config;
39
+ private readonly config;
146
40
  private eventBuffer;
147
41
  private flushTimer;
148
42
  private lastEmittedStatus;
149
- private static readonly EVENT_BATCH_MS;
150
43
  private earlyMessages;
151
44
  private earlyStop;
152
45
  private earlySoftStop;
153
46
  private earlyModeChanges;
154
- private chatMessageCallback;
47
+ private messageCallback;
155
48
  private stopCallback;
156
49
  private softStopCallback;
157
50
  private modeChangeCallback;
158
- private runStartCommandCallback;
159
- private pendingQuestionResolvers;
160
- constructor(config: AgentRunnerConfig);
51
+ private wakeCallback;
52
+ private apiKeyUpdateCallback;
53
+ constructor(config: AgentConnectionConfig);
54
+ get sessionId(): string;
55
+ get connected(): boolean;
56
+ call<M extends keyof AgentSessionServiceMethods>(method: M, payload: AgentSessionServiceMethods[M]["payload"]): Promise<AgentSessionServiceMethods[M]["response"]>;
161
57
  connect(): Promise<void>;
162
- fetchChatMessages(limit?: number, taskId?: string): Promise<ChatMessageResponse[]>;
163
- fetchTaskFiles(): Promise<TaskFileResponse[]>;
164
- fetchTaskFile(fileId: string): Promise<TaskFileResponse>;
165
- fetchTaskContext(): Promise<TaskContext>;
166
- sendEvent(event: AgentEvent): void;
167
- flushEvents(): void;
168
- updateStatus(status: string): void;
58
+ disconnect(): void;
59
+ onMessage(callback: (msg: IncomingMessage) => void): void;
60
+ onStop(callback: () => void): void;
61
+ onSoftStop(callback: () => void): void;
62
+ onModeChange(callback: (data: SetModeData) => void): void;
63
+ onWake(callback: () => void): void;
64
+ onApiKeyUpdate(callback: (data: ApiKeyUpdateData) => void): void;
65
+ emitStatus(status: string): void;
169
66
  postChatMessage(content: string): void;
170
- createPR(params: {
171
- title: string;
172
- body: string;
173
- baseBranch?: string;
174
- branch?: string;
175
- }): Promise<{
176
- url: string;
177
- number: number;
178
- }>;
179
- askUserQuestion(requestId: string, questions: AgentQuestion[]): Promise<Record<string, string>>;
180
- cancelPendingQuestions(): void;
181
- storeSessionId(sessionId: string): void;
67
+ sendHeartbeat(): void;
68
+ emitModeChanged(agentMode?: AgentMode | null): void;
182
69
  updateTaskFields(fields: {
183
70
  plan?: string;
184
71
  description?: string;
185
72
  }): void;
186
- onChatMessage(callback: (message: IncomingMessagePayload) => void): void;
187
- onStopRequested(callback: () => void): void;
188
- onSoftStopRequested(callback: () => void): void;
189
- onModeChange(callback: (data: SetModePayload) => void): void;
190
- onRunStartCommand(callback: () => void): void;
191
- private handleRunAuthTokenCommand;
192
- emitModeChanged(agentMode?: AgentMode | null): void;
73
+ storeSessionId(sdkSessionId: string): void;
74
+ sendTypingStart(): void;
75
+ sendTypingStop(): void;
193
76
  trackSpending(params: {
194
77
  agentId: string;
195
78
  sessionId: string;
196
79
  totalCostUsd: number;
197
80
  onSubscription: boolean;
198
- modelUsage?: {
199
- model: string;
200
- inputTokens: number;
201
- outputTokens: number;
202
- cacheReadInputTokens: number;
203
- cacheCreationInputTokens: number;
204
- costUSD: number;
205
- }[];
81
+ modelUsage?: ModelUsageEntry[];
206
82
  }): void;
207
- emitStatus(status: string): void;
208
83
  emitRateLimitPause(resetsAt: string): void;
209
- sendHeartbeat(): void;
210
- sendTypingStart(): void;
211
- sendTypingStop(): void;
212
- createSubtask(data: SubtaskCreatePayload): Promise<{
213
- id: string;
214
- }>;
215
- updateSubtask(subtaskId: string, fields: SubtaskUpdateFields): void;
216
- deleteSubtask(subtaskId: string): void;
217
- listSubtasks(): Promise<SubtaskResponse[]>;
218
- fetchCliHistory(taskId?: string, limit?: number, source?: string): Promise<{
219
- event: AgentEvent;
220
- time: string;
221
- }[]>;
222
- startChildCloudBuild(childTaskId: string): Promise<StartChildCloudBuildResponse>;
223
- approveAndMergePR(childTaskId: string): Promise<{
224
- merged: boolean;
225
- queued?: boolean;
226
- childTaskId: string;
227
- prNumber: number;
228
- }>;
229
- postChildChatMessage(childTaskId: string, content: string): Promise<void>;
230
- updateChildStatus(childTaskId: string, status: string): Promise<void>;
231
- stopChildBuild(childTaskId: string): Promise<void>;
232
- fetchTask(slugOrId: string): Promise<TaskLookupResponse>;
233
- updateTaskProperties(data: UpdateTaskPropertiesPayload): void;
234
- listIcons(): Promise<IconListItem[]>;
235
- generateTaskIcon(prompt: string, aspectRatio?: "auto" | "portrait" | "landscape" | "square"): Promise<GenerateIconResponse>;
236
- getTaskProperties(): Promise<TaskPropertiesResponse>;
237
- triggerIdentification(): Promise<TriggerIdentificationResponse>;
238
- refreshAuthToken(): Promise<boolean>;
239
- emitModeTransition(payload: ModeTransitionPayload): void;
240
- emitDebugStateChanged(state: DebugSessionState): void;
241
- emitDebugSessionComplete(summary: DebugSessionSummary): void;
242
- emitDebugReproduceRequested(hypothesis?: string): void;
84
+ updateStatus(status: string): void;
243
85
  emitCodeReviewResult(content: string, approved: boolean): void;
244
- searchIncidents(status?: string, source?: string): Promise<IncidentDTO[]>;
245
- getTaskIncidents(taskId?: string): Promise<TaskIncidentDTO[]>;
246
- requestScaleUp(tier: ResourceTierName, reason?: string): Promise<ScaleUpResponse>;
247
- addDependency(dependsOnSlugOrId: string): Promise<void>;
248
- removeDependency(dependsOnSlugOrId: string): Promise<void>;
249
- getDependencies(): Promise<TaskDependencySummary[]>;
250
- createFollowUpTask(data: {
251
- title: string;
252
- description?: string;
86
+ askUserQuestion(questions: AgentQuestion[]): Promise<Record<string, string>>;
87
+ getTaskProperties(): Promise<{
253
88
  plan?: string;
254
- storyPointValue?: number;
255
- }): Promise<{
256
- id: string;
257
- slug: string;
89
+ storyPointId?: string;
90
+ title?: string;
258
91
  }>;
259
- queryGcpLogs(params: {
260
- filter?: string;
261
- startTime?: string;
262
- endTime?: string;
263
- severity?: string;
264
- pageSize?: number;
265
- }): Promise<QueryGcpLogsResponse>;
266
- createSuggestion(title: string, description?: string, tagNames?: string[]): Promise<{
267
- id: string;
268
- merged: boolean;
269
- mergedIntoId?: string;
92
+ triggerIdentification(): Promise<{
93
+ identified: boolean;
270
94
  }>;
271
- voteSuggestion(suggestionId: string, value: 1 | -1): Promise<{
272
- score: number;
95
+ requestScaleUp(tier: string, reason?: string): Promise<{
96
+ scaled: boolean;
273
97
  }>;
274
- getSuggestions(status?: string, limit?: number): Promise<Array<{
275
- id: string;
276
- title: string;
277
- description: string | null;
278
- score: number;
279
- status: string;
280
- tags: string[];
281
- }>>;
282
- disconnect(): void;
98
+ refreshAuthToken(): Promise<boolean>;
99
+ sendEvent(event: Record<string, unknown>): void;
100
+ flushEvents(): void;
101
+ }
102
+
103
+ type ModeAction = {
104
+ type: "noop";
105
+ } | {
106
+ type: "restart_query";
107
+ newMode: AgentMode;
108
+ } | {
109
+ type: "soft_stop";
110
+ } | {
111
+ type: "start_auto";
112
+ };
113
+ interface ModeTaskContext {
114
+ status: string;
115
+ plan: string | null;
116
+ storyPointId: string | null;
117
+ isParentTask?: boolean;
118
+ model: string;
119
+ builderModel?: string | null;
120
+ githubPRUrl?: string | null;
121
+ }
122
+ declare class ModeController {
123
+ private _mode;
124
+ private _hasExitedPlanMode;
125
+ private _pendingModeRestart;
126
+ private _runnerMode;
127
+ private _isAuto;
128
+ constructor(initialMode: AgentMode, runnerMode?: "task" | "pm" | "code-review", isAuto?: boolean);
129
+ get mode(): AgentMode;
130
+ get hasExitedPlanMode(): boolean;
131
+ set hasExitedPlanMode(val: boolean);
132
+ get pendingModeRestart(): boolean;
133
+ set pendingModeRestart(val: boolean);
134
+ /** Effective mode accounting for PM/task defaults */
135
+ get effectiveMode(): AgentMode;
136
+ get isReadOnly(): boolean;
137
+ get isAutoPlanning(): boolean;
138
+ get isBuildCapable(): boolean;
139
+ /** Resolve the initial mode based on task context */
140
+ resolveInitialMode(context: ModeTaskContext): AgentMode;
141
+ /** Check if auto-mode can bypass planning (task already has plan + properties) */
142
+ canBypassPlanning(context: ModeTaskContext): boolean;
143
+ /** Handle mode change from server */
144
+ handleModeChange(newMode: AgentMode): ModeAction;
145
+ /** Handle ExitPlanMode call from the agent */
146
+ handleExitPlanMode(context: ModeTaskContext): ModeAction;
147
+ /** Check if pack runner behavior should be used */
148
+ isPackRunner(context: ModeTaskContext): boolean;
149
+ private transitionToBuilding;
150
+ private updateExitedPlanModeFlag;
151
+ }
152
+
153
+ interface LifecycleConfig {
154
+ /** Idle timeout before entering sleep mode (default: 30 min) */
155
+ idleTimeoutMs: number;
156
+ /** Grace period after sleep announcement before shutdown (default: 5s) */
157
+ sleepGracePeriodMs: number;
158
+ /** Heartbeat interval (default: 30s) */
159
+ heartbeatIntervalMs: number;
160
+ }
161
+ interface LifecycleCallbacks {
162
+ onHeartbeat: () => void;
163
+ onIdleTimeout: () => void;
164
+ onSleep: () => void;
165
+ onSleepGraceExpired: () => void;
166
+ onWake: () => void;
167
+ }
168
+ /** 30 min idle, 5s sleep grace, 30s heartbeat */
169
+ declare const DEFAULT_LIFECYCLE_CONFIG: LifecycleConfig;
170
+ declare class Lifecycle {
171
+ private readonly config;
172
+ private readonly callbacks;
173
+ private heartbeatTimer;
174
+ private idleTimer;
175
+ private idleCheckInterval;
176
+ private sleepShutdownTimer;
177
+ private _isSleeping;
178
+ constructor(config: LifecycleConfig, callbacks: LifecycleCallbacks);
179
+ get isSleeping(): boolean;
180
+ startHeartbeat(): void;
181
+ stopHeartbeat(): void;
182
+ startIdleTimer(): void;
183
+ cancelIdleTimer(): void;
184
+ private enterSleepMode;
185
+ /** Wake from sleep — cancels shutdown timer, resets idle */
186
+ wake(): void;
187
+ /** Cancel the sleep shutdown timer (e.g. when a message arrives) */
188
+ cancelSleepShutdown(): void;
189
+ destroy(): void;
190
+ private clearIdleTimers;
191
+ }
192
+
193
+ interface SessionRunnerConfig {
194
+ connection: AgentConnectionConfig;
195
+ agentMode?: AgentMode;
196
+ runnerMode?: "task" | "pm" | "code-review";
197
+ isAuto?: boolean;
198
+ workspaceDir: string;
199
+ model?: string;
200
+ lifecycle?: Partial<LifecycleConfig>;
201
+ }
202
+ interface SessionRunnerCallbacks {
203
+ onStatusChange: (status: AgentRunnerStatus) => void | Promise<void>;
204
+ onEvent: (event: Record<string, unknown>) => void | Promise<void>;
205
+ }
206
+ declare class SessionRunner {
207
+ readonly connection: AgentConnection;
208
+ readonly mode: ModeController;
209
+ readonly lifecycle: Lifecycle;
210
+ private readonly config;
211
+ private readonly callbacks;
212
+ private _state;
213
+ private stopped;
214
+ private interrupted;
215
+ private taskContext;
216
+ private fullContext;
217
+ private queryBridge;
218
+ private inputResolver;
219
+ private pendingMessages;
220
+ private prNudgeCount;
221
+ constructor(config: SessionRunnerConfig, callbacks: SessionRunnerCallbacks);
222
+ get state(): AgentRunnerStatus;
223
+ get sessionId(): string;
224
+ get isStopped(): boolean;
225
+ start(): Promise<void>;
226
+ private coreLoop;
227
+ private executeInitialMode;
228
+ private waitForMessage;
229
+ /** Inject a message (from connection callback or external source) */
230
+ injectMessage(msg: IncomingMessage): void;
231
+ stop(): void;
232
+ softStop(): void;
233
+ private static readonly MAX_PR_NUDGES;
234
+ private needsPRNudge;
235
+ private refreshTaskContext;
236
+ private maybeSendPRNudge;
237
+ private buildFullContext;
238
+ private createQueryBridge;
239
+ private wireConnectionCallbacks;
240
+ private setState;
241
+ private shutdown;
242
+ private logInitialization;
243
+ }
244
+
245
+ interface AgentRunnerConfig {
246
+ conveyorApiUrl: string;
247
+ taskToken: string;
248
+ taskId: string;
249
+ model: string;
250
+ instructions: string;
251
+ workspaceDir: string;
252
+ mode?: _project_shared.RunnerMode;
253
+ isAuto?: boolean;
254
+ agentSettings?: _project_shared.AgentSettings;
255
+ }
256
+ interface AgentRunnerCallbacks {
257
+ onEvent: (event: Record<string, unknown>) => void | Promise<void>;
258
+ onStatusChange: (status: string) => void | Promise<void>;
283
259
  }
284
260
 
285
261
  interface ProjectConnectionConfig {
286
262
  apiUrl: string;
287
263
  projectToken: string;
288
264
  projectId: string;
289
- projectDir?: string;
290
265
  }
291
266
  interface TaskAssignment {
292
267
  taskId: string;
293
268
  taskToken: string;
269
+ sessionId?: string;
294
270
  apiUrl: string;
295
271
  mode: string;
296
272
  branch: string;
@@ -304,151 +280,106 @@ interface IncomingChatMessage {
304
280
  content: string;
305
281
  userId: string;
306
282
  chatId?: string;
307
- files?: {
308
- id: string;
309
- fileName: string;
310
- mimeType: string;
311
- downloadUrl: string;
312
- content?: string;
313
- contentEncoding?: "base64" | "utf-8";
314
- }[];
315
- }
316
- interface ChatHistoryMessage {
317
- role: string;
318
- content: string;
319
- userId: string | null;
320
- userName?: string;
321
- createdAt: string;
322
- }
323
- interface AgentContext {
324
- projectName: string;
325
- projectDescription: string | null;
326
- agentId: string | null;
327
- agentName: string | null;
328
- agentInstructions: string;
329
- model: string;
330
- agentSettings: Record<string, unknown> | null;
331
- branchSwitchCommand?: string;
332
- }
333
- type SwitchBranchCallback = (res: {
334
- ok: boolean;
335
- data?: _project_shared.ProjectEnvironmentStatus;
336
- error?: string;
337
- }) => void;
338
- type SyncEnvironmentCallback = (res: {
339
- ok: boolean;
340
- data?: _project_shared.ProjectEnvironmentStatus;
341
- error?: string;
342
- }) => void;
343
- type GetEnvStatusCallback = (res: {
344
- ok: boolean;
345
- data?: _project_shared.ProjectEnvironmentStatus;
346
- }) => void;
283
+ projectId: string;
284
+ timestamp: string;
285
+ }
286
+ interface SwitchBranchRequest {
287
+ branch: string;
288
+ syncAfter?: boolean;
289
+ }
347
290
  declare class ProjectConnection {
348
291
  private socket;
349
- private config;
350
- private taskAssignmentCallback;
351
- private stopTaskCallback;
352
- private shutdownCallback;
353
- private chatMessageCallback;
354
- private earlyChatMessages;
355
- private auditRequestCallback;
356
- onSwitchBranch: ((data: {
357
- branch: string;
358
- syncAfter?: boolean;
359
- }, cb: SwitchBranchCallback) => void) | null;
360
- onSyncEnvironment: ((cb: SyncEnvironmentCallback) => void) | null;
361
- onGetEnvStatus: ((cb: GetEnvStatusCallback) => void) | null;
362
- onRestartStartCommand: ((cb: (res: {
363
- ok: boolean;
364
- error?: string;
365
- }) => void) => void) | null;
292
+ private readonly config;
293
+ private eventBuffer;
294
+ private flushTimer;
295
+ private reconnectCallbacks;
366
296
  constructor(config: ProjectConnectionConfig);
297
+ get projectId(): string;
298
+ get connected(): boolean;
299
+ call<M extends keyof AgentSessionServiceMethods>(method: M, payload: AgentSessionServiceMethods[M]["payload"]): Promise<AgentSessionServiceMethods[M]["response"]>;
367
300
  connect(): Promise<void>;
301
+ disconnect(): void;
302
+ onReconnect(callback: () => void): void;
368
303
  onTaskAssignment(callback: (assignment: TaskAssignment) => void): void;
369
304
  onStopTask(callback: (data: {
370
305
  taskId: string;
371
306
  }) => void): void;
372
307
  onShutdown(callback: () => void): void;
373
308
  onChatMessage(callback: (msg: IncomingChatMessage) => void): void;
374
- onAuditRequest(callback: (request: TagAuditRunnerRequest) => void): void;
375
- emitAuditResult(data: TagAuditRunnerResponse): void;
376
- emitAuditProgress(data: {
377
- requestId: string;
378
- activity: TagAuditProgressActivity;
379
- }): void;
309
+ onSwitchBranch(callback: (data: SwitchBranchRequest, cb: (res: {
310
+ ok: boolean;
311
+ error?: string;
312
+ }) => void) => void): void;
313
+ onSyncEnvironment(callback: (cb: (res: {
314
+ ok: boolean;
315
+ error?: string;
316
+ }) => void) => void): void;
317
+ onRestartStartCommand(callback: (cb: (res: {
318
+ ok: boolean;
319
+ error?: string;
320
+ }) => void) => void): void;
380
321
  sendHeartbeat(): void;
322
+ sendEvent(event: Record<string, unknown>): void;
323
+ emitStatus(status: "busy" | "idle"): void;
381
324
  emitTaskStarted(taskId: string): void;
382
325
  emitTaskStopped(taskId: string, reason: string): void;
383
- emitEvent(event: Record<string, unknown>): void;
384
- emitChatMessage(content: string): Promise<void>;
385
- emitAgentStatus(status: string): void;
386
- fetchAgentContext(): Promise<AgentContext | null>;
387
- fetchChatHistory(limit?: number, chatId?: string): Promise<ChatHistoryMessage[]>;
388
- requestListTasks(params: {
389
- status?: string;
390
- assigneeId?: string;
391
- limit?: number;
392
- }): Promise<unknown[]>;
393
- requestGetTask(taskId: string): Promise<unknown>;
394
- requestCreateTask(params: {
395
- title: string;
396
- description?: string;
397
- plan?: string;
398
- status?: string;
399
- isBug?: boolean;
400
- }): Promise<{
401
- id: string;
402
- slug: string;
403
- }>;
404
- requestUpdateTask(params: {
405
- taskId: string;
406
- title?: string;
407
- description?: string;
408
- plan?: string;
409
- status?: string;
410
- assignedUserId?: string | null;
411
- }): Promise<unknown>;
412
- requestSearchTasks(params: {
413
- tagNames?: string[];
414
- searchQuery?: string;
415
- statusFilters?: string[];
416
- limit?: number;
417
- }): Promise<unknown[]>;
418
- requestListTags(): Promise<unknown[]>;
419
- requestGetProjectSummary(): Promise<unknown>;
420
- private requestWithCallback;
421
- emitNewCommitsDetected(data: {
422
- branch: string;
423
- commitCount: number;
424
- latestCommit: {
425
- sha: string;
426
- message: string;
427
- author: string;
428
- };
429
- autoSyncing: boolean;
430
- }): void;
431
- emitEnvironmentReady(data: {
432
- branch: string;
433
- commitsSynced: number;
434
- syncDurationMs: number;
435
- stepsRun: string[];
436
- }): void;
437
- emitEnvSwitchProgress(data: {
438
- step: string;
439
- status: "running" | "success" | "error";
440
- message?: string;
441
- }): void;
442
- private handleRunAuthTokenCommand;
443
- disconnect(): void;
326
+ private flushEvents;
327
+ private requireSocket;
444
328
  }
445
329
 
446
- declare function ensureWorktree(projectDir: string, taskId: string, branch?: string): string;
447
- /**
448
- * Force-remove is intentional: this runs after task completion or explicit stop.
449
- * Any uncommitted changes at this point are scratch artifacts, not valuable work.
450
- */
451
- declare function removeWorktree(projectDir: string, taskId: string): void;
330
+ interface ProjectRunnerConfig {
331
+ conveyorApiUrl: string;
332
+ projectToken: string;
333
+ projectId: string;
334
+ projectDir: string;
335
+ }
336
+ declare class ProjectRunner {
337
+ private connection;
338
+ private projectDir;
339
+ private activeAgents;
340
+ private heartbeatTimer;
341
+ private stopping;
342
+ private resolveLifecycle;
343
+ private chatSessionIds;
344
+ private startCommandChild;
345
+ private startCommandRunning;
346
+ private setupComplete;
347
+ private branchSwitchCommand;
348
+ private commitWatcher;
349
+ constructor(config: ProjectRunnerConfig);
350
+ start(): Promise<void>;
351
+ stop(): Promise<void>;
352
+ private wireEventHandlers;
353
+ private handleReconnect;
354
+ private handleAssignment;
355
+ private handleStopTask;
356
+ private checkoutWorkspaceBranch;
357
+ private executeSetupCommand;
358
+ private executeStartCommand;
359
+ private killStartCommand;
360
+ private restartStartCommand;
361
+ private getCurrentBranch;
362
+ private handleSwitchBranch;
363
+ private handleSyncEnvironment;
364
+ private handleNewCommits;
365
+ private smartSync;
366
+ private syncDependencies;
367
+ private runIndividualSyncSteps;
368
+ private getChangedFiles;
369
+ }
370
+
371
+ declare class PlanSync {
372
+ private planFileSnapshot;
373
+ private lockedPlanFile;
374
+ private workspaceDir;
375
+ private connection;
376
+ constructor(workspaceDir: string, connection: AgentConnection);
377
+ updateWorkspaceDir(workspaceDir: string): void;
378
+ private getPlanDirs;
379
+ snapshotPlanFiles(): void;
380
+ private findNewestPlanFile;
381
+ syncPlanFile(): void;
382
+ }
452
383
 
453
384
  interface CacheEntry {
454
385
  content: Buffer;
@@ -474,18 +405,63 @@ declare class FileCache {
474
405
  };
475
406
  }
476
407
 
477
- interface ConveyorConfig {
478
- setupCommand?: string;
479
- startCommand?: string;
480
- previewPort?: number;
408
+ interface CommitWatcherConfig {
409
+ projectDir: string;
410
+ pollIntervalMs: number;
411
+ debounceMs: number;
412
+ }
413
+ interface NewCommitsData {
414
+ branch: string;
415
+ previousSha: string;
416
+ newCommitSha: string;
417
+ commitCount: number;
418
+ latestMessage: string;
419
+ latestAuthor: string;
420
+ }
421
+ interface CommitWatcherCallbacks {
422
+ onNewCommits: (data: NewCommitsData) => Promise<void>;
481
423
  }
424
+ declare class CommitWatcher {
425
+ private config;
426
+ private callbacks;
427
+ private interval;
428
+ private lastKnownRemoteSha;
429
+ private branch;
430
+ private debounceTimer;
431
+ private isSyncing;
432
+ constructor(config: CommitWatcherConfig, callbacks: CommitWatcherCallbacks);
433
+ start(branch: string): void;
434
+ stop(): void;
435
+ private getLocalHeadSha;
436
+ private poll;
437
+ private handleNewCommits;
438
+ }
439
+
440
+ /** Returns true if the working tree has uncommitted changes (staged or unstaged). */
441
+ declare function hasUncommittedChanges(cwd: string): boolean;
442
+ /** Returns the current branch name, or null if on detached HEAD. */
443
+ declare function getCurrentBranch(cwd: string): string | null;
444
+ /** Returns true if there are committed changes that haven't been pushed to origin. */
445
+ declare function hasUnpushedCommits(cwd: string): boolean;
446
+ /** Stage all changes and create a commit. Returns the commit hash if successful. */
447
+ declare function stageAndCommit(cwd: string, message: string): string | null;
448
+ /** Update the git remote URL with a fresh token. */
449
+ declare function updateRemoteToken(cwd: string, token: string): void;
450
+ /** Push current branch to origin. On auth failure, refreshes the GitHub token and retries. */
451
+ declare function pushToOrigin(cwd: string, refreshToken?: () => Promise<string | undefined>): Promise<boolean>;
452
+
453
+ declare function ensureWorktree(projectDir: string, taskId: string, branch?: string): string;
482
454
  /**
483
- * Load config from env vars (project-level settings injected via bootstrap).
455
+ * Detach any task worktree that has `branch` checked out, releasing the branch lock
456
+ * so the main project directory can check it out. Only touches worktrees inside
457
+ * `.worktrees/` — never the main project directory.
484
458
  */
485
- declare function loadConveyorConfig(_workspaceDir?: string): ConveyorConfig | null;
486
-
487
- declare function runSetupCommand(cmd: string, cwd: string, onOutput: (stream: "stdout" | "stderr", data: string) => void): Promise<void>;
488
- declare function runStartCommand(cmd: string, cwd: string, onOutput: (stream: "stdout" | "stderr", data: string) => void): ChildProcess;
459
+ declare function detachWorktreeBranch(projectDir: string, branch: string): void;
460
+ /**
461
+ * Force-remove is intentional: this runs after task completion or explicit stop.
462
+ * Any uncommitted changes at this point are scratch artifacts, not valuable work.
463
+ */
464
+ declare function removeWorktree(projectDir: string, taskId: string): void;
489
465
 
490
466
  interface BreakpointInfo {
491
467
  breakpointId: string;
@@ -664,6 +640,7 @@ declare class PlaywrightDebugClient {
664
640
  private clearInactivityTimer;
665
641
  }
666
642
 
643
+ type InspectorRuntime = "node" | "bun" | "unknown";
667
644
  interface DebugEventHandler {
668
645
  onDebugModeEntered: () => void;
669
646
  onDebugModeExited: () => void;
@@ -703,11 +680,13 @@ declare class DebugManager {
703
680
  private ensurePlaywrightInstalled;
704
681
  private startWithInspector;
705
682
  }
683
+ declare function detectRuntime(startCommand: string): InspectorRuntime;
684
+ declare function injectBunInspectFlag(command: string): string;
706
685
 
707
686
  /**
708
687
  * Orchestrates the debug session lifecycle, tracks state for the web UI,
709
688
  * and generates session summaries. Wraps DebugManager events and forwards
710
- * state changes to the API via ConveyorConnection.
689
+ * state changes to the API via AgentConnection.
711
690
  */
712
691
  declare class DebugLifecycleManager {
713
692
  private connection;
@@ -719,7 +698,7 @@ declare class DebugLifecycleManager {
719
698
  private reproduceRequested;
720
699
  private keyFindings;
721
700
  private _isActive;
722
- constructor(connection: ConveyorConnection);
701
+ constructor(connection: AgentConnection);
723
702
  get isActive(): boolean;
724
703
  setDebugManager(manager: DebugManager): void;
725
704
  /**
@@ -743,4 +722,71 @@ declare class DebugLifecycleManager {
743
722
  private broadcastState;
744
723
  }
745
724
 
746
- export { type AgentContext, AgentRunner, type AgentRunnerCallbacks, type AgentRunnerConfig, type BreakpointInfo, type CallFrameInfo, CdpDebugClient, type ChatHistoryMessage, type ConveyorConfig, ConveyorConnection, type DebugEventHandler, DebugLifecycleManager, DebugManager, FileCache, type IncomingChatMessage, type PausedState, ProjectConnection, type ProjectConnectionConfig, ProjectRunner, type ProjectRunnerConfig, type ScopeVariable, type TaskAssignment, ensureWorktree, loadConveyorConfig, removeWorktree, runSetupCommand, runStartCommand };
725
+ interface Observation {
726
+ description: string;
727
+ confirmsHypothesis: boolean;
728
+ iteration: number;
729
+ timestamp: number;
730
+ }
731
+ interface HypothesisState {
732
+ hypothesis: string | null;
733
+ iteration: number;
734
+ observations: Observation[];
735
+ active: boolean;
736
+ conclusion: string | null;
737
+ }
738
+ declare class HypothesisTracker {
739
+ private hypothesis;
740
+ private iteration;
741
+ private observations;
742
+ private _active;
743
+ private conclusion;
744
+ /**
745
+ * Start or update the current debugging hypothesis.
746
+ * Increments the iteration count if a hypothesis was already set.
747
+ */
748
+ setHypothesis(text: string): {
749
+ accepted: boolean;
750
+ message: string;
751
+ };
752
+ /**
753
+ * Record an observation from debug data (breakpoint hit, telemetry, etc.).
754
+ */
755
+ recordObservation(description: string, confirmsHypothesis: boolean): void;
756
+ /**
757
+ * End the debug session with a conclusion.
758
+ */
759
+ concludeSession(conclusion: string): string;
760
+ /**
761
+ * Get formatted debug context for injection into the agent's system prompt.
762
+ * Returns empty string if no active session.
763
+ */
764
+ getDebugContext(): string;
765
+ /**
766
+ * Get the full state (for serialization/testing).
767
+ */
768
+ getState(): HypothesisState;
769
+ isActive(): boolean;
770
+ getIteration(): number;
771
+ getMaxIterations(): number;
772
+ private getSessionSummary;
773
+ private reset;
774
+ }
775
+
776
+ interface ConveyorConfig {
777
+ setupCommand?: string;
778
+ startCommand?: string;
779
+ previewPort?: number;
780
+ }
781
+ declare function loadForwardPorts(workspaceDir: string): Promise<number[]>;
782
+ /** Load config from env vars (project-level settings injected via bootstrap). */
783
+ declare function loadConveyorConfig(): ConveyorConfig | null;
784
+
785
+ declare function runSetupCommand(cmd: string, cwd: string, onOutput: (stream: "stdout" | "stderr", data: string) => void): Promise<void>;
786
+ declare function runAuthTokenCommand(cmd: string, userEmail: string, cwd: string): string | null;
787
+ declare function runStartCommand(cmd: string, cwd: string, onOutput: (stream: "stdout" | "stderr", data: string) => void): ChildProcess;
788
+
789
+ /** Fetch full git history if the repo was cloned with --depth=1. */
790
+ declare function unshallowRepo(workspaceDir: string): void;
791
+
792
+ export { AgentConnection, type AgentConnectionConfig, type AgentRunnerCallbacks, type AgentRunnerConfig, type ApiKeyUpdateData, CommitWatcher, type ConveyorConfig, DEFAULT_LIFECYCLE_CONFIG, type DebugEventHandler, DebugLifecycleManager, DebugManager, type DebugModeOptions, FileCache, HypothesisTracker, type IncomingMessage, type InspectorRuntime, Lifecycle, type LifecycleCallbacks, type LifecycleConfig, type ModeAction, ModeController, type ModeTaskContext, PlanSync, ProjectConnection, ProjectRunner, SessionRunner, type SessionRunnerCallbacks, type SessionRunnerConfig, type SetModeData, detachWorktreeBranch, detectRuntime, ensureWorktree, getCurrentBranch, hasUncommittedChanges, hasUnpushedCommits, injectBunInspectFlag, loadConveyorConfig, loadForwardPorts, pushToOrigin, removeWorktree, runAuthTokenCommand, runSetupCommand, runStartCommand, stageAndCommit, unshallowRepo, updateRemoteToken };