@schilderlabs/pitown-core 0.1.1 → 0.2.6

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 @@
1
+ export { };
@@ -0,0 +1,122 @@
1
+ import { S as writeAgentState, _ as getLatestAgentSession, c as appendAgentMessage, d as getAgentDir, l as createAgentSessionRecord, o as updateTaskRecordStatus, u as createAgentState, x as readAgentState } from "./tasks-BfQm-7-O.mjs";
2
+ import { createWriteStream, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { spawn } from "node:child_process";
4
+ import { finished } from "node:stream/promises";
5
+
6
+ //#region src/agent-runner.ts
7
+ async function waitForChild(child) {
8
+ return new Promise((resolve) => {
9
+ let error = null;
10
+ child.once("error", (value) => {
11
+ error = value;
12
+ });
13
+ child.once("close", (code) => {
14
+ resolve({
15
+ exitCode: code ?? 1,
16
+ error
17
+ });
18
+ });
19
+ });
20
+ }
21
+ async function runDetachedAgent(payload) {
22
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
23
+ const agentArtifactsDir = getAgentDir(payload.artifactsDir, payload.agentId);
24
+ const stdoutPath = `${agentArtifactsDir}/latest-stdout.txt`;
25
+ const stderrPath = `${agentArtifactsDir}/latest-stderr.txt`;
26
+ const invocationPath = `${agentArtifactsDir}/latest-invocation.json`;
27
+ mkdirSync(agentArtifactsDir, { recursive: true });
28
+ const stdoutStream = createWriteStream(stdoutPath, { encoding: "utf-8" });
29
+ const stderrStream = createWriteStream(stderrPath, { encoding: "utf-8" });
30
+ const child = spawn("pi", payload.piArgs, {
31
+ cwd: payload.repoRoot,
32
+ env: process.env,
33
+ stdio: [
34
+ "ignore",
35
+ "pipe",
36
+ "pipe"
37
+ ]
38
+ });
39
+ if (child.stdout) child.stdout.pipe(stdoutStream);
40
+ if (child.stderr) child.stderr.pipe(stderrStream);
41
+ const currentState = readAgentState(payload.artifactsDir, payload.agentId);
42
+ if (currentState) writeAgentState(payload.artifactsDir, createAgentState({
43
+ ...currentState,
44
+ status: "running",
45
+ lastMessage: payload.task ? `Running ${payload.role} task: ${payload.task}` : `Running ${payload.role} agent`,
46
+ waitingOn: null,
47
+ blocked: false,
48
+ session: createAgentSessionRecord({
49
+ sessionDir: payload.sessionDir,
50
+ sessionId: currentState.session.sessionId,
51
+ sessionPath: currentState.session.sessionPath,
52
+ processId: child.pid ?? null,
53
+ lastAttachedAt: currentState.session.lastAttachedAt
54
+ })
55
+ }));
56
+ writeFileSync(invocationPath, `${JSON.stringify({
57
+ command: "pi",
58
+ args: payload.piArgs,
59
+ exitCode: null,
60
+ sessionDir: payload.sessionDir,
61
+ sessionPath: null,
62
+ sessionId: null,
63
+ processId: child.pid ?? null,
64
+ startedAt
65
+ }, null, 2)}\n`, "utf-8");
66
+ const { exitCode, error } = await waitForChild(child);
67
+ if (!stdoutStream.writableEnded) stdoutStream.end();
68
+ if (!stderrStream.writableEnded) stderrStream.end();
69
+ await Promise.all([finished(stdoutStream), finished(stderrStream)]);
70
+ const stdout = readFileSync(stdoutPath, "utf-8");
71
+ const stderr = readFileSync(stderrPath, "utf-8");
72
+ const latestSession = getLatestAgentSession(payload.artifactsDir, payload.agentId);
73
+ const completionMessage = stdout.trim() || (error?.message?.trim() ?? "") || (exitCode === 0 ? `${payload.role} run completed` : `${payload.role} run exited with code ${exitCode}`);
74
+ if (error) writeFileSync(stderrPath, `${stderr}${stderr.endsWith("\n") || stderr.length === 0 ? "" : "\n"}${error.message}\n`, "utf-8");
75
+ writeFileSync(invocationPath, `${JSON.stringify({
76
+ command: "pi",
77
+ args: payload.piArgs,
78
+ exitCode,
79
+ sessionDir: latestSession.sessionDir ?? payload.sessionDir,
80
+ sessionPath: latestSession.sessionPath,
81
+ sessionId: latestSession.sessionId,
82
+ processId: child.pid ?? null,
83
+ startedAt,
84
+ endedAt: (/* @__PURE__ */ new Date()).toISOString()
85
+ }, null, 2)}\n`, "utf-8");
86
+ appendAgentMessage({
87
+ artifactsDir: payload.artifactsDir,
88
+ agentId: payload.agentId,
89
+ box: "outbox",
90
+ from: payload.agentId,
91
+ body: completionMessage
92
+ });
93
+ if (payload.taskId) updateTaskRecordStatus(payload.artifactsDir, payload.taskId, exitCode === 0 ? "completed" : "blocked");
94
+ const finalState = readAgentState(payload.artifactsDir, payload.agentId);
95
+ if (finalState) writeAgentState(payload.artifactsDir, createAgentState({
96
+ ...finalState,
97
+ status: exitCode === 0 ? "idle" : "blocked",
98
+ lastMessage: completionMessage,
99
+ waitingOn: exitCode === 0 ? null : "human-or-follow-up-run",
100
+ blocked: exitCode !== 0,
101
+ session: createAgentSessionRecord({
102
+ sessionDir: latestSession.sessionDir ?? payload.sessionDir,
103
+ sessionId: latestSession.sessionId,
104
+ sessionPath: latestSession.sessionPath,
105
+ processId: null,
106
+ lastAttachedAt: finalState.session.lastAttachedAt
107
+ })
108
+ }));
109
+ }
110
+ async function main() {
111
+ const [encodedPayload] = process.argv.slice(2);
112
+ if (!encodedPayload) throw new Error("Missing detached agent payload");
113
+ await runDetachedAgent(JSON.parse(Buffer.from(encodedPayload, "base64url").toString("utf-8")));
114
+ }
115
+ main().catch((error) => {
116
+ console.error(error instanceof Error ? error.stack ?? error.message : String(error));
117
+ process.exitCode = 1;
118
+ });
119
+
120
+ //#endregion
121
+ export { };
122
+ //# sourceMappingURL=agent-runner.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-runner.mjs","names":[],"sources":["../src/agent-runner.ts"],"sourcesContent":["import { spawn } from \"node:child_process\"\nimport { createWriteStream, mkdirSync, readFileSync, writeFileSync } from \"node:fs\"\nimport { finished } from \"node:stream/promises\"\nimport {\n\tappendAgentMessage,\n\tcreateAgentSessionRecord,\n\tcreateAgentState,\n\tgetAgentDir,\n\tgetLatestAgentSession,\n\treadAgentState,\n\twriteAgentState,\n} from \"./agents.js\"\nimport { updateTaskRecordStatus } from \"./tasks.js\"\n\ninterface DetachedAgentRunPayload {\n\trepoRoot: string\n\tartifactsDir: string\n\tagentId: string\n\trole: string\n\ttask: string | null\n\ttaskId: string | null\n\tsessionDir: string\n\tpiArgs: string[]\n}\n\ninterface ChildCompletion {\n\texitCode: number\n\terror: Error | null\n}\n\nasync function waitForChild(child: ReturnType<typeof spawn>): Promise<ChildCompletion> {\n\treturn new Promise((resolve) => {\n\t\tlet error: Error | null = null\n\t\tchild.once(\"error\", (value) => {\n\t\t\terror = value\n\t\t})\n\t\tchild.once(\"close\", (code) => {\n\t\t\tresolve({\n\t\t\t\texitCode: code ?? 1,\n\t\t\t\terror,\n\t\t\t})\n\t\t})\n\t})\n}\n\nasync function runDetachedAgent(payload: DetachedAgentRunPayload) {\n\tconst startedAt = new Date().toISOString()\n\tconst agentArtifactsDir = getAgentDir(payload.artifactsDir, payload.agentId)\n\tconst stdoutPath = `${agentArtifactsDir}/latest-stdout.txt`\n\tconst stderrPath = `${agentArtifactsDir}/latest-stderr.txt`\n\tconst invocationPath = `${agentArtifactsDir}/latest-invocation.json`\n\tmkdirSync(agentArtifactsDir, { recursive: true })\n\n\tconst stdoutStream = createWriteStream(stdoutPath, { encoding: \"utf-8\" })\n\tconst stderrStream = createWriteStream(stderrPath, { encoding: \"utf-8\" })\n\tconst child = spawn(\"pi\", payload.piArgs, {\n\t\tcwd: payload.repoRoot,\n\t\tenv: process.env,\n\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t})\n\n\tif (child.stdout) child.stdout.pipe(stdoutStream)\n\tif (child.stderr) child.stderr.pipe(stderrStream)\n\n\tconst currentState = readAgentState(payload.artifactsDir, payload.agentId)\n\tif (currentState) {\n\t\twriteAgentState(\n\t\t\tpayload.artifactsDir,\n\t\t\tcreateAgentState({\n\t\t\t\t...currentState,\n\t\t\t\tstatus: \"running\",\n\t\t\t\tlastMessage: payload.task ? `Running ${payload.role} task: ${payload.task}` : `Running ${payload.role} agent`,\n\t\t\t\twaitingOn: null,\n\t\t\t\tblocked: false,\n\t\t\t\tsession: createAgentSessionRecord({\n\t\t\t\t\tsessionDir: payload.sessionDir,\n\t\t\t\t\tsessionId: currentState.session.sessionId,\n\t\t\t\t\tsessionPath: currentState.session.sessionPath,\n\t\t\t\t\tprocessId: child.pid ?? null,\n\t\t\t\t\tlastAttachedAt: currentState.session.lastAttachedAt,\n\t\t\t\t}),\n\t\t\t}),\n\t\t)\n\t}\n\n\twriteFileSync(\n\t\tinvocationPath,\n\t\t`${JSON.stringify(\n\t\t\t{\n\t\t\t\tcommand: \"pi\",\n\t\t\t\targs: payload.piArgs,\n\t\t\t\texitCode: null,\n\t\t\t\tsessionDir: payload.sessionDir,\n\t\t\t\tsessionPath: null,\n\t\t\t\tsessionId: null,\n\t\t\t\tprocessId: child.pid ?? null,\n\t\t\t\tstartedAt,\n\t\t\t},\n\t\t\tnull,\n\t\t\t2,\n\t\t)}\\n`,\n\t\t\"utf-8\",\n\t)\n\n\tconst { exitCode, error } = await waitForChild(child)\n\tif (!stdoutStream.writableEnded) stdoutStream.end()\n\tif (!stderrStream.writableEnded) stderrStream.end()\n\tawait Promise.all([finished(stdoutStream), finished(stderrStream)])\n\n\tconst stdout = readFileSync(stdoutPath, \"utf-8\")\n\tconst stderr = readFileSync(stderrPath, \"utf-8\")\n\tconst latestSession = getLatestAgentSession(payload.artifactsDir, payload.agentId)\n\tconst completionMessage =\n\t\tstdout.trim() ||\n\t\t(error?.message?.trim() ?? \"\") ||\n\t\t(exitCode === 0 ? `${payload.role} run completed` : `${payload.role} run exited with code ${exitCode}`)\n\n\tif (error) {\n\t\twriteFileSync(stderrPath, `${stderr}${stderr.endsWith(\"\\n\") || stderr.length === 0 ? \"\" : \"\\n\"}${error.message}\\n`, \"utf-8\")\n\t}\n\n\twriteFileSync(\n\t\tinvocationPath,\n\t\t`${JSON.stringify(\n\t\t\t{\n\t\t\t\tcommand: \"pi\",\n\t\t\t\targs: payload.piArgs,\n\t\t\t\texitCode,\n\t\t\t\tsessionDir: latestSession.sessionDir ?? payload.sessionDir,\n\t\t\t\tsessionPath: latestSession.sessionPath,\n\t\t\t\tsessionId: latestSession.sessionId,\n\t\t\t\tprocessId: child.pid ?? null,\n\t\t\t\tstartedAt,\n\t\t\t\tendedAt: new Date().toISOString(),\n\t\t\t},\n\t\t\tnull,\n\t\t\t2,\n\t\t)}\\n`,\n\t\t\"utf-8\",\n\t)\n\n\tappendAgentMessage({\n\t\tartifactsDir: payload.artifactsDir,\n\t\tagentId: payload.agentId,\n\t\tbox: \"outbox\",\n\t\tfrom: payload.agentId,\n\t\tbody: completionMessage,\n\t})\n\n\tif (payload.taskId) {\n\t\tupdateTaskRecordStatus(payload.artifactsDir, payload.taskId, exitCode === 0 ? \"completed\" : \"blocked\")\n\t}\n\n\tconst finalState = readAgentState(payload.artifactsDir, payload.agentId)\n\tif (finalState) {\n\t\twriteAgentState(\n\t\t\tpayload.artifactsDir,\n\t\t\tcreateAgentState({\n\t\t\t\t...finalState,\n\t\t\t\tstatus: exitCode === 0 ? \"idle\" : \"blocked\",\n\t\t\t\tlastMessage: completionMessage,\n\t\t\t\twaitingOn: exitCode === 0 ? null : \"human-or-follow-up-run\",\n\t\t\t\tblocked: exitCode !== 0,\n\t\t\t\tsession: createAgentSessionRecord({\n\t\t\t\t\tsessionDir: latestSession.sessionDir ?? payload.sessionDir,\n\t\t\t\t\tsessionId: latestSession.sessionId,\n\t\t\t\t\tsessionPath: latestSession.sessionPath,\n\t\t\t\t\tprocessId: null,\n\t\t\t\t\tlastAttachedAt: finalState.session.lastAttachedAt,\n\t\t\t\t}),\n\t\t\t}),\n\t\t)\n\t}\n}\n\nasync function main() {\n\tconst [encodedPayload] = process.argv.slice(2)\n\tif (!encodedPayload) {\n\t\tthrow new Error(\"Missing detached agent payload\")\n\t}\n\n\tconst payload = JSON.parse(Buffer.from(encodedPayload, \"base64url\").toString(\"utf-8\")) as DetachedAgentRunPayload\n\tawait runDetachedAgent(payload)\n}\n\nvoid main().catch((error) => {\n\tconsole.error(error instanceof Error ? error.stack ?? error.message : String(error))\n\tprocess.exitCode = 1\n})\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -2,6 +2,48 @@
2
2
  type InterruptCategory = "missing-context" | "spec-gap" | "policy-gap" | "validation-gap" | "tooling-failure" | "external-blocker";
3
3
  type FixType = "adr" | "docs" | "policy" | "prompt" | "skill" | "tooling" | "validation";
4
4
  type RunMode = "single-pi";
5
+ type AgentStatus = "queued" | "starting" | "running" | "idle" | "blocked" | "completed" | "failed" | "stopped";
6
+ type AgentMailbox = "inbox" | "outbox";
7
+ type TaskStatus = "queued" | "running" | "blocked" | "completed" | "aborted";
8
+ interface AgentSessionRecord {
9
+ runtime: "pi";
10
+ persisted: boolean;
11
+ sessionDir: string | null;
12
+ sessionId: string | null;
13
+ sessionPath: string | null;
14
+ processId: number | null;
15
+ lastAttachedAt: string | null;
16
+ }
17
+ interface AgentStateSnapshot {
18
+ agentId: string;
19
+ role: string;
20
+ status: AgentStatus;
21
+ taskId: string | null;
22
+ task: string | null;
23
+ branch: string | null;
24
+ updatedAt: string;
25
+ lastMessage: string | null;
26
+ waitingOn: string | null;
27
+ blocked: boolean;
28
+ runId: string | null;
29
+ session: AgentSessionRecord;
30
+ }
31
+ interface AgentMessageRecord {
32
+ box: AgentMailbox;
33
+ from: string;
34
+ body: string;
35
+ createdAt: string;
36
+ }
37
+ interface TaskRecord {
38
+ taskId: string;
39
+ title: string;
40
+ status: TaskStatus;
41
+ role: string;
42
+ assignedAgentId: string;
43
+ createdBy: string;
44
+ createdAt: string;
45
+ updatedAt: string;
46
+ }
5
47
  interface InterruptRecord {
6
48
  id: string;
7
49
  runId: string;
@@ -47,6 +89,8 @@ interface RunOptions {
47
89
  mode?: RunMode;
48
90
  planPath?: string | null;
49
91
  recommendedPlanDir?: string | null;
92
+ appendedSystemPrompt?: string | null;
93
+ extensionPath?: string | null;
50
94
  piCommand?: string;
51
95
  }
52
96
  interface RunManifest {
@@ -75,6 +119,9 @@ interface PiInvocationRecord {
75
119
  repoRoot: string;
76
120
  planPath: string | null;
77
121
  goal: string | null;
122
+ sessionDir: string | null;
123
+ sessionId: string | null;
124
+ sessionPath: string | null;
78
125
  startedAt: string;
79
126
  endedAt: string;
80
127
  exitCode: number;
@@ -100,6 +147,84 @@ interface ControllerRunResult {
100
147
  summary: RunSummary;
101
148
  piInvocation: PiInvocationRecord;
102
149
  }
150
+ type LoopStopReason = "all-tasks-completed" | "all-remaining-tasks-blocked" | "mayor-blocked" | "mayor-idle-no-work" | "max-iterations-reached" | "max-wall-time-reached" | "pi-exit-nonzero" | "high-interrupt-rate";
151
+ interface LoopOptions {
152
+ runOptions: RunOptions;
153
+ maxIterations?: number;
154
+ maxWallTimeMs?: number;
155
+ stopOnPiFailure?: boolean;
156
+ stopOnMayorIdleNoWork?: boolean;
157
+ interruptRateThreshold?: number | null;
158
+ onIterationComplete?: (iteration: LoopIterationResult) => void;
159
+ }
160
+ interface BoardSnapshot {
161
+ tasks: Array<{
162
+ taskId: string;
163
+ status: TaskStatus;
164
+ }>;
165
+ agents: Array<{
166
+ agentId: string;
167
+ status: AgentStatus;
168
+ blocked: boolean;
169
+ }>;
170
+ allTasksCompleted: boolean;
171
+ allRemainingTasksBlocked: boolean;
172
+ mayorBlocked: boolean;
173
+ hasQueuedOrRunningWork: boolean;
174
+ }
175
+ interface LoopIterationResult {
176
+ iteration: number;
177
+ controllerResult: ControllerRunResult;
178
+ boardSnapshot: BoardSnapshot;
179
+ metrics: MetricsSnapshot;
180
+ elapsedMs: number;
181
+ continueReason: string | null;
182
+ stopReason: LoopStopReason | null;
183
+ }
184
+ interface LoopRunResult {
185
+ loopId: string;
186
+ iterations: LoopIterationResult[];
187
+ stopReason: LoopStopReason;
188
+ totalIterations: number;
189
+ totalElapsedMs: number;
190
+ finalBoardSnapshot: BoardSnapshot;
191
+ aggregateMetrics: MetricsSnapshot;
192
+ }
193
+ //#endregion
194
+ //#region src/agents.d.ts
195
+ declare function getAgentsDir(artifactsDir: string): string;
196
+ declare function getAgentDir(artifactsDir: string, agentId: string): string;
197
+ declare function getAgentStatePath(artifactsDir: string, agentId: string): string;
198
+ declare function getAgentSessionPath(artifactsDir: string, agentId: string): string;
199
+ declare function getAgentMailboxPath(artifactsDir: string, agentId: string, box: AgentMailbox): string;
200
+ declare function getAgentSessionsDir(artifactsDir: string, agentId: string): string;
201
+ declare function getSessionIdFromPath(sessionPath: string | null | undefined): string | null;
202
+ declare function createAgentSessionRecord(input?: Partial<Pick<AgentSessionRecord, "sessionDir" | "sessionId" | "sessionPath" | "processId" | "lastAttachedAt">>): AgentSessionRecord;
203
+ declare function createAgentState(input: {
204
+ agentId: string;
205
+ role: string;
206
+ status: AgentStatus;
207
+ taskId?: string | null;
208
+ task?: string | null;
209
+ branch?: string | null;
210
+ lastMessage?: string | null;
211
+ waitingOn?: string | null;
212
+ blocked?: boolean;
213
+ runId?: string | null;
214
+ session?: AgentSessionRecord;
215
+ }): AgentStateSnapshot;
216
+ declare function writeAgentState(artifactsDir: string, state: AgentStateSnapshot): void;
217
+ declare function readAgentState(artifactsDir: string, agentId: string): AgentStateSnapshot | null;
218
+ declare function listAgentStates(artifactsDir: string): AgentStateSnapshot[];
219
+ declare function appendAgentMessage(input: {
220
+ artifactsDir: string;
221
+ agentId: string;
222
+ box: AgentMailbox;
223
+ from: string;
224
+ body: string;
225
+ }): AgentMessageRecord;
226
+ declare function readAgentMessages(artifactsDir: string, agentId: string, box: AgentMailbox): AgentMessageRecord[];
227
+ declare function getLatestAgentSession(artifactsDir: string, agentId: string): AgentSessionRecord;
103
228
  //#endregion
104
229
  //#region src/controller.d.ts
105
230
  declare function runController(options: RunOptions): ControllerRunResult;
@@ -127,6 +252,25 @@ declare function acquireRepoLease(runId: string, repoId: string, branch: string)
127
252
  release: () => void;
128
253
  };
129
254
  //#endregion
255
+ //#region src/loop.d.ts
256
+ declare function snapshotBoard(artifactsDir: string): BoardSnapshot;
257
+ declare function evaluateStopCondition(input: {
258
+ iteration: number;
259
+ maxIterations: number;
260
+ elapsedMs: number;
261
+ maxWallTimeMs: number;
262
+ piExitCode: number;
263
+ stopOnPiFailure: boolean;
264
+ stopOnMayorIdleNoWork: boolean;
265
+ board: BoardSnapshot;
266
+ metrics: MetricsSnapshot;
267
+ interruptRateThreshold: number | null;
268
+ }): {
269
+ stopReason: LoopStopReason | null;
270
+ continueReason: string | null;
271
+ };
272
+ declare function runLoop(options: LoopOptions): LoopRunResult;
273
+ //#endregion
130
274
  //#region src/metrics.d.ts
131
275
  declare function computeInterruptRate(interrupts: InterruptRecord[], taskAttempts: TaskAttempt[]): number;
132
276
  declare function computeAutonomousCompletionRate(taskAttempts: TaskAttempt[]): number;
@@ -139,6 +283,89 @@ declare function computeMetrics(input: {
139
283
  feedbackCycles?: FeedbackCycle[];
140
284
  }): MetricsSnapshot;
141
285
  //#endregion
286
+ //#region src/orchestration.d.ts
287
+ interface SpawnAgentRunOptions {
288
+ repoRoot: string;
289
+ artifactsDir: string;
290
+ role: string;
291
+ agentId: string;
292
+ task: string | null;
293
+ appendedSystemPrompt?: string | null | undefined;
294
+ extensionPath?: string | null | undefined;
295
+ taskId?: string | null | undefined;
296
+ }
297
+ interface SpawnAgentRunResult {
298
+ launch: {
299
+ processId: number;
300
+ startedAt: string;
301
+ };
302
+ latestSession: AgentSessionRecord;
303
+ }
304
+ interface DelegateTaskOptions {
305
+ repoRoot: string;
306
+ artifactsDir: string;
307
+ fromAgentId: string;
308
+ role: string;
309
+ agentId?: string | null | undefined;
310
+ appendedSystemPrompt?: string | null | undefined;
311
+ extensionPath?: string | null | undefined;
312
+ task: string;
313
+ }
314
+ interface DelegateTaskResult {
315
+ task: TaskRecord;
316
+ agentId: string;
317
+ launch: SpawnAgentRunResult["launch"];
318
+ latestSession: AgentSessionRecord;
319
+ }
320
+ interface ResolvedAgentSession {
321
+ state: AgentStateSnapshot;
322
+ session: AgentSessionRecord;
323
+ }
324
+ interface RunAgentTurnOptions {
325
+ repoRoot: string;
326
+ artifactsDir: string;
327
+ agentId: string;
328
+ message: string;
329
+ from?: string;
330
+ runtimeArgs?: string[] | null;
331
+ }
332
+ interface RunAgentTurnResult {
333
+ piResult: {
334
+ stdout: string;
335
+ stderr: string;
336
+ exitCode: number;
337
+ };
338
+ latestSession: AgentSessionRecord;
339
+ completionMessage: string;
340
+ }
341
+ declare function createRolePrompt(input: {
342
+ role: string;
343
+ task: string | null;
344
+ repoRoot: string;
345
+ }): string;
346
+ declare function resolveAgentSession(agentId: string, artifactsDir: string): ResolvedAgentSession;
347
+ declare function queueAgentMessage(input: {
348
+ artifactsDir: string;
349
+ agentId: string;
350
+ from: string;
351
+ body: string;
352
+ }): void;
353
+ declare function updateAgentStatus(input: {
354
+ artifactsDir: string;
355
+ agentId: string;
356
+ status: "queued" | "running" | "idle" | "blocked" | "completed" | "failed" | "stopped";
357
+ lastMessage?: string | null;
358
+ waitingOn?: string | null;
359
+ blocked?: boolean;
360
+ }): void;
361
+ declare function spawnAgentRun(options: SpawnAgentRunOptions): SpawnAgentRunResult;
362
+ declare function runAgentTurn(options: RunAgentTurnOptions): RunAgentTurnResult;
363
+ declare function delegateTask(options: DelegateTaskOptions): DelegateTaskResult;
364
+ //#endregion
365
+ //#region src/pi.d.ts
366
+ declare function detectPiAuthFailure(stderr: string, stdout: string): boolean;
367
+ declare function createPiAuthHelpMessage(): string;
368
+ //#endregion
142
369
  //#region src/repo.d.ts
143
370
  declare function isGitRepo(cwd: string): boolean;
144
371
  declare function getRepoRoot(cwd: string): string;
@@ -157,7 +384,83 @@ declare function runCommandSync(command: string, args: string[], options?: {
157
384
  env?: NodeJS.ProcessEnv;
158
385
  }): CommandResult;
159
386
  declare function assertCommandAvailable(command: string): void;
387
+ declare function runCommandInteractive(command: string, args: string[], options?: {
388
+ cwd?: string;
389
+ env?: NodeJS.ProcessEnv;
390
+ }): number;
160
391
  declare function assertSuccess(result: CommandResult, context: string): void;
161
392
  //#endregion
162
- export { CommandResult, ControllerRunResult, CreateInterruptInput, FeedbackCycle, FixType, InterruptCategory, InterruptRecord, MetricsSnapshot, PiInvocationRecord, RunManifest, RunMode, RunOptions, RunSummary, TaskAttempt, acquireRepoLease, appendJsonl, assertCommandAvailable, assertSuccess, computeAutonomousCompletionRate, computeContextCoverageScore, computeFeedbackToDemoCycleTime, computeInterruptRate, computeMeanTimeToCorrect, computeMetrics, createInterruptRecord, createRepoSlug, getCurrentBranch, getRepoIdentity, getRepoRoot, isGitRepo, readJsonl, resolveInterrupt, runCommandSync, runController };
393
+ //#region src/stop.d.ts
394
+ interface LeaseData {
395
+ runId: string;
396
+ repoId: string;
397
+ branch: string;
398
+ pid: number;
399
+ hostname: string;
400
+ startedAt: string;
401
+ }
402
+ interface StopManagedAgentsOptions {
403
+ artifactsDir: string;
404
+ agentId?: string | null;
405
+ excludeAgentIds?: string[];
406
+ actorId?: string | null;
407
+ reason?: string | null;
408
+ force?: boolean;
409
+ graceMs?: number;
410
+ }
411
+ interface StopAgentResult {
412
+ agentId: string;
413
+ previousStatus: AgentStateSnapshot["status"];
414
+ nextStatus: AgentStateSnapshot["status"];
415
+ processId: number | null;
416
+ signal: "SIGTERM" | "SIGKILL" | null;
417
+ exited: boolean;
418
+ }
419
+ interface StopManagedAgentsResult {
420
+ results: StopAgentResult[];
421
+ stoppedAgents: number;
422
+ signaledProcesses: number;
423
+ }
424
+ interface RepoLeaseRecord extends LeaseData {
425
+ path: string;
426
+ }
427
+ interface StopRepoLeasesOptions {
428
+ repoId?: string | null;
429
+ force?: boolean;
430
+ graceMs?: number;
431
+ }
432
+ interface StopRepoLeaseResult {
433
+ path: string;
434
+ runId: string;
435
+ repoId: string;
436
+ branch: string;
437
+ processId: number;
438
+ signal: "SIGTERM" | "SIGKILL" | null;
439
+ exited: boolean;
440
+ }
441
+ interface StopRepoLeasesResult {
442
+ results: StopRepoLeaseResult[];
443
+ signaledProcesses: number;
444
+ }
445
+ declare function listRepoLeases(repoId?: string | null): RepoLeaseRecord[];
446
+ declare function stopRepoLeases(options: StopRepoLeasesOptions): StopRepoLeasesResult;
447
+ declare function stopManagedAgents(options: StopManagedAgentsOptions): StopManagedAgentsResult;
448
+ //#endregion
449
+ //#region src/tasks.d.ts
450
+ declare function getTasksDir(artifactsDir: string): string;
451
+ declare function getTaskPath(artifactsDir: string, taskId: string): string;
452
+ declare function createTaskRecord(input: {
453
+ taskId: string;
454
+ title: string;
455
+ status: TaskStatus;
456
+ role: string;
457
+ assignedAgentId: string;
458
+ createdBy: string;
459
+ }): TaskRecord;
460
+ declare function writeTaskRecord(artifactsDir: string, task: TaskRecord): void;
461
+ declare function updateTaskRecordStatus(artifactsDir: string, taskId: string, status: TaskStatus): TaskRecord | null;
462
+ declare function readTaskRecord(artifactsDir: string, taskId: string): TaskRecord | null;
463
+ declare function listTaskRecords(artifactsDir: string): TaskRecord[];
464
+ //#endregion
465
+ export { AgentMailbox, AgentMessageRecord, AgentSessionRecord, AgentStateSnapshot, AgentStatus, BoardSnapshot, CommandResult, ControllerRunResult, CreateInterruptInput, DelegateTaskOptions, DelegateTaskResult, FeedbackCycle, FixType, InterruptCategory, InterruptRecord, LoopIterationResult, LoopOptions, LoopRunResult, LoopStopReason, MetricsSnapshot, PiInvocationRecord, RepoLeaseRecord, ResolvedAgentSession, RunAgentTurnOptions, RunAgentTurnResult, RunManifest, RunMode, RunOptions, RunSummary, SpawnAgentRunOptions, SpawnAgentRunResult, StopAgentResult, StopManagedAgentsOptions, StopManagedAgentsResult, StopRepoLeaseResult, StopRepoLeasesOptions, StopRepoLeasesResult, TaskAttempt, TaskRecord, TaskStatus, acquireRepoLease, appendAgentMessage, appendJsonl, assertCommandAvailable, assertSuccess, computeAutonomousCompletionRate, computeContextCoverageScore, computeFeedbackToDemoCycleTime, computeInterruptRate, computeMeanTimeToCorrect, computeMetrics, createAgentSessionRecord, createAgentState, createInterruptRecord, createPiAuthHelpMessage, createRepoSlug, createRolePrompt, createTaskRecord, delegateTask, detectPiAuthFailure, evaluateStopCondition, getAgentDir, getAgentMailboxPath, getAgentSessionPath, getAgentSessionsDir, getAgentStatePath, getAgentsDir, getCurrentBranch, getLatestAgentSession, getRepoIdentity, getRepoRoot, getSessionIdFromPath, getTaskPath, getTasksDir, isGitRepo, listAgentStates, listRepoLeases, listTaskRecords, queueAgentMessage, readAgentMessages, readAgentState, readJsonl, readTaskRecord, resolveAgentSession, resolveInterrupt, runAgentTurn, runCommandInteractive, runCommandSync, runController, runLoop, snapshotBoard, spawnAgentRun, stopManagedAgents, stopRepoLeases, updateAgentStatus, updateTaskRecordStatus, writeAgentState, writeTaskRecord };
163
466
  //# sourceMappingURL=index.d.mts.map