@schilderlabs/pitown 0.1.2 → 0.2.1
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/README.md +19 -0
- package/dist/{config-Bw-mNdF5.mjs → config-CUpe9o0x.mjs} +30 -50
- package/dist/config-CUpe9o0x.mjs.map +1 -0
- package/dist/{controller-D7lezZjg.mjs → controller-9ihAZj3V.mjs} +193 -10
- package/dist/controller-9ihAZj3V.mjs.map +1 -0
- package/dist/doctor.d.mts +8 -0
- package/dist/doctor.mjs +42 -0
- package/dist/doctor.mjs.map +1 -0
- package/dist/entrypoint-CyJDLudQ.mjs +61 -0
- package/dist/entrypoint-CyJDLudQ.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1235 -6
- package/dist/index.mjs.map +1 -1
- package/dist/pi-C0fURZj7.mjs +12 -0
- package/dist/pi-C0fURZj7.mjs.map +1 -0
- package/dist/run.d.mts +3 -0
- package/dist/run.mjs +8 -3
- package/dist/run.mjs.map +1 -1
- package/dist/status.mjs +2 -1
- package/dist/status.mjs.map +1 -1
- package/dist/watch.mjs +2 -1
- package/dist/watch.mjs.map +1 -1
- package/package.json +7 -5
- package/dist/config-Bw-mNdF5.mjs.map +0 -1
- package/dist/controller-D7lezZjg.mjs.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { isDirectExecution } from \"./entrypoint.js\"\nimport { runTown } from \"./run.js\"\nimport { showTownStatus } from \"./status.js\"\nimport { watchTown } from \"./watch.js\"\n\nexport function printHelp() {\n\tconsole.log(\n\t\t[\n\t\t\t\"pitown\",\n\t\t\t\"\",\n\t\t\t\"Usage:\",\n\t\t\t\" pitown run [--repo <path>] [--plan <path>] [--goal <text>]\",\n\t\t\t\" pitown status [--repo <path>]\",\n\t\t\t\" pitown watch [--repo <path>]\",\n\t\t\t\" pitown help\",\n\t\t\t\" pitown --help\",\n\t\t].join(\"\\n\"),\n\t)\n}\n\nexport function runCli(argv = process.argv.slice(2)) {\n\tconst [command, ...args] = argv\n\n\tswitch (command) {\n\t\tcase undefined:\n\t\tcase \"help\":\n\t\tcase \"--help\":\n\t\tcase \"-h\":\n\t\t\tprintHelp()\n\t\t\tbreak\n\t\tcase \"run\": {\n\t\t\tconst result = runTown(args)\n\t\t\tif (result.piInvocation.exitCode !== 0) process.exitCode = result.piInvocation.exitCode\n\t\t\tbreak\n\t\t}\n\t\tcase \"status\":\n\t\t\tshowTownStatus(args)\n\t\t\tbreak\n\t\tcase \"watch\":\n\t\t\twatchTown(args)\n\t\t\tbreak\n\t\tdefault:\n\t\t\tconsole.log(`Unknown command: ${command}`)\n\t\t\tprintHelp()\n\t\t\tprocess.exitCode = 1\n\t\t\tbreak\n\t}\n}\n\nif (isDirectExecution(import.meta.url)) {\n\trunCli()\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,YAAY;AAC3B,SAAQ,IACP;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC,KAAK,KAAK,CACZ;;AAGF,SAAgB,OAAO,OAAO,QAAQ,KAAK,MAAM,EAAE,EAAE;CACpD,MAAM,CAAC,SAAS,GAAG,QAAQ;AAE3B,SAAQ,SAAR;EACC,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;AACJ,cAAW;AACX;EACD,KAAK,OAAO;GACX,MAAM,SAAS,QAAQ,KAAK;AAC5B,OAAI,OAAO,aAAa,aAAa,EAAG,SAAQ,WAAW,OAAO,aAAa;AAC/E;;EAED,KAAK;AACJ,kBAAe,KAAK;AACpB;EACD,KAAK;AACJ,aAAU,KAAK;AACf;EACD;AACC,WAAQ,IAAI,oBAAoB,UAAU;AAC1C,cAAW;AACX,WAAQ,WAAW;AACnB;;;AAIH,IAAI,kBAAkB,OAAO,KAAK,IAAI,CACrC,SAAQ"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["writeJson","DEFAULT_MAX_ITERATIONS","packageJson.version"],"sources":["../../core/src/tasks.ts","../../core/src/loop.ts","../../core/src/orchestration.ts","../src/agent-id.ts","../src/pi-runtime.ts","../src/repo-context.ts","../src/attach.ts","../src/board.ts","../src/continue.ts","../src/delegate.ts","../src/loop-config.ts","../src/loop.ts","../src/mayor.ts","../src/msg.ts","../src/peek.ts","../src/spawn.ts","../package.json","../src/version.ts","../src/index.ts"],"sourcesContent":["import { mkdirSync, readFileSync, readdirSync, writeFileSync } from \"node:fs\"\nimport { dirname, join } from \"node:path\"\nimport type { TaskRecord, TaskStatus } from \"./types.js\"\n\nfunction writeJson(path: string, value: unknown) {\n\tmkdirSync(dirname(path), { recursive: true })\n\twriteFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\")\n}\n\nexport function getTasksDir(artifactsDir: string): string {\n\treturn join(artifactsDir, \"tasks\")\n}\n\nexport function getTaskPath(artifactsDir: string, taskId: string): string {\n\treturn join(getTasksDir(artifactsDir), `${taskId}.json`)\n}\n\nexport function createTaskRecord(input: {\n\ttaskId: string\n\ttitle: string\n\tstatus: TaskStatus\n\trole: string\n\tassignedAgentId: string\n\tcreatedBy: string\n}): TaskRecord {\n\tconst now = new Date().toISOString()\n\treturn {\n\t\ttaskId: input.taskId,\n\t\ttitle: input.title,\n\t\tstatus: input.status,\n\t\trole: input.role,\n\t\tassignedAgentId: input.assignedAgentId,\n\t\tcreatedBy: input.createdBy,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t}\n}\n\nexport function writeTaskRecord(artifactsDir: string, task: TaskRecord) {\n\twriteJson(getTaskPath(artifactsDir, task.taskId), task)\n}\n\nexport function updateTaskRecordStatus(artifactsDir: string, taskId: string, status: TaskStatus): TaskRecord | null {\n\tconst task = readTaskRecord(artifactsDir, taskId)\n\tif (task === null) return null\n\n\tconst updatedTask: TaskRecord = {\n\t\t...task,\n\t\tstatus,\n\t\tupdatedAt: new Date().toISOString(),\n\t}\n\twriteTaskRecord(artifactsDir, updatedTask)\n\treturn updatedTask\n}\n\nexport function readTaskRecord(artifactsDir: string, taskId: string): TaskRecord | null {\n\tconst path = getTaskPath(artifactsDir, taskId)\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, \"utf-8\")) as TaskRecord\n\t} catch {\n\t\treturn null\n\t}\n}\n\nexport function listTaskRecords(artifactsDir: string): TaskRecord[] {\n\tconst tasksDir = getTasksDir(artifactsDir)\n\tlet entries: string[]\n\ttry {\n\t\tentries = readdirSync(tasksDir)\n\t} catch {\n\t\treturn []\n\t}\n\n\treturn entries\n\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t.map((entry) => readTaskRecord(artifactsDir, entry.replace(/\\.json$/, \"\")))\n\t\t.filter((task): task is TaskRecord => task !== null)\n\t\t.sort((left, right) => left.taskId.localeCompare(right.taskId))\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { listAgentStates } from \"./agents.js\"\nimport { runController } from \"./controller.js\"\nimport { appendJsonl } from \"./events.js\"\nimport { computeMetrics } from \"./metrics.js\"\nimport { listTaskRecords } from \"./tasks.js\"\nimport type {\n\tBoardSnapshot,\n\tControllerRunResult,\n\tLoopIterationResult,\n\tLoopOptions,\n\tLoopRunResult,\n\tLoopStopReason,\n\tMetricsSnapshot,\n} from \"./types.js\"\n\nconst DEFAULT_MAX_ITERATIONS = 10\nconst DEFAULT_MAX_WALL_TIME_MS = 3_600_000\n\nfunction createLoopId(): string {\n\treturn `loop-${new Date().toISOString().replace(/[:.]/g, \"-\")}`\n}\n\nfunction writeJson(path: string, value: unknown) {\n\twriteFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\")\n}\n\nexport function snapshotBoard(artifactsDir: string): BoardSnapshot {\n\tconst tasks = listTaskRecords(artifactsDir)\n\tconst agents = listAgentStates(artifactsDir)\n\n\tconst taskEntries = tasks.map((task) => ({ taskId: task.taskId, status: task.status }))\n\tconst agentEntries = agents.map((agent) => ({\n\t\tagentId: agent.agentId,\n\t\tstatus: agent.status,\n\t\tblocked: agent.blocked,\n\t}))\n\n\tconst allTasksCompleted = tasks.length > 0 && tasks.every((task) => task.status === \"completed\")\n\tconst allRemainingTasksBlocked =\n\t\ttasks.length > 0 && tasks.every((task) => task.status === \"completed\" || task.status === \"blocked\")\n\n\tconst leader = agents.find((agent) => agent.agentId === \"leader\")\n\tconst leaderBlocked = leader?.blocked === true\n\n\tconst hasQueuedOrRunningWork =\n\t\tagents.some((agent) => agent.status === \"queued\" || agent.status === \"running\" || agent.status === \"starting\") ||\n\t\ttasks.some((task) => task.status === \"queued\" || task.status === \"running\")\n\n\treturn {\n\t\ttasks: taskEntries,\n\t\tagents: agentEntries,\n\t\tallTasksCompleted,\n\t\tallRemainingTasksBlocked,\n\t\tleaderBlocked,\n\t\thasQueuedOrRunningWork,\n\t}\n}\n\nexport function evaluateStopCondition(input: {\n\titeration: number\n\tmaxIterations: number\n\telapsedMs: number\n\tmaxWallTimeMs: number\n\tpiExitCode: number\n\tstopOnPiFailure: boolean\n\tboard: BoardSnapshot\n\tmetrics: MetricsSnapshot\n\tinterruptRateThreshold: number | null\n}): { stopReason: LoopStopReason | null; continueReason: string | null } {\n\tif (input.iteration >= input.maxIterations) {\n\t\treturn { stopReason: \"max-iterations-reached\", continueReason: null }\n\t}\n\n\tif (input.elapsedMs >= input.maxWallTimeMs) {\n\t\treturn { stopReason: \"max-wall-time-reached\", continueReason: null }\n\t}\n\n\tif (input.stopOnPiFailure && input.piExitCode !== 0) {\n\t\treturn { stopReason: \"pi-exit-nonzero\", continueReason: null }\n\t}\n\n\tif (input.board.allTasksCompleted) {\n\t\treturn { stopReason: \"all-tasks-completed\", continueReason: null }\n\t}\n\n\tif (input.board.leaderBlocked) {\n\t\treturn { stopReason: \"leader-blocked\", continueReason: null }\n\t}\n\n\tif (input.board.allRemainingTasksBlocked) {\n\t\treturn { stopReason: \"all-remaining-tasks-blocked\", continueReason: null }\n\t}\n\n\tif (\n\t\tinput.interruptRateThreshold !== null &&\n\t\tinput.metrics.interruptRate > input.interruptRateThreshold\n\t) {\n\t\treturn { stopReason: \"high-interrupt-rate\", continueReason: null }\n\t}\n\n\tconst reasons: string[] = []\n\tif (input.board.hasQueuedOrRunningWork) reasons.push(\"queued or running work remains\")\n\tif (input.board.tasks.length === 0) reasons.push(\"no tasks tracked yet\")\n\tif (reasons.length === 0) reasons.push(\"leader idle, no stop condition met\")\n\n\treturn { stopReason: null, continueReason: reasons.join(\"; \") }\n}\n\nfunction aggregateMetrics(iterations: LoopIterationResult[]): MetricsSnapshot {\n\tif (iterations.length === 0) {\n\t\treturn computeMetrics({ taskAttempts: [], interrupts: [] })\n\t}\n\n\tlet totalTaskAttempts = 0\n\tlet totalCompletedTasks = 0\n\tlet totalInterrupts = 0\n\tlet totalObservedInterruptCategories = 0\n\tlet totalCoveredInterruptCategories = 0\n\tlet interruptRateSum = 0\n\tlet autonomousCompletionRateSum = 0\n\tlet contextCoverageScoreSum = 0\n\tlet mttcValues: number[] = []\n\tlet ftdValues: number[] = []\n\n\tfor (const iter of iterations) {\n\t\tconst m = iter.metrics\n\t\ttotalTaskAttempts += m.totals.taskAttempts\n\t\ttotalCompletedTasks += m.totals.completedTasks\n\t\ttotalInterrupts += m.totals.interrupts\n\t\ttotalObservedInterruptCategories += m.totals.observedInterruptCategories\n\t\ttotalCoveredInterruptCategories += m.totals.coveredInterruptCategories\n\t\tinterruptRateSum += m.interruptRate\n\t\tautonomousCompletionRateSum += m.autonomousCompletionRate\n\t\tcontextCoverageScoreSum += m.contextCoverageScore\n\t\tif (m.meanTimeToCorrectHours !== null) mttcValues.push(m.meanTimeToCorrectHours)\n\t\tif (m.feedbackToDemoCycleTimeHours !== null) ftdValues.push(m.feedbackToDemoCycleTimeHours)\n\t}\n\n\tconst count = iterations.length\n\tconst round = (v: number) => Math.round(v * 1000) / 1000\n\tconst avg = (values: number[]) => (values.length === 0 ? null : round(values.reduce((s, v) => s + v, 0) / values.length))\n\n\treturn {\n\t\tinterruptRate: round(interruptRateSum / count),\n\t\tautonomousCompletionRate: round(autonomousCompletionRateSum / count),\n\t\tcontextCoverageScore: round(contextCoverageScoreSum / count),\n\t\tmeanTimeToCorrectHours: avg(mttcValues),\n\t\tfeedbackToDemoCycleTimeHours: avg(ftdValues),\n\t\ttotals: {\n\t\t\ttaskAttempts: totalTaskAttempts,\n\t\t\tcompletedTasks: totalCompletedTasks,\n\t\t\tinterrupts: totalInterrupts,\n\t\t\tobservedInterruptCategories: totalObservedInterruptCategories,\n\t\t\tcoveredInterruptCategories: totalCoveredInterruptCategories,\n\t\t},\n\t}\n}\n\nexport function runLoop(options: LoopOptions): LoopRunResult {\n\tconst maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS\n\tconst maxWallTimeMs = options.maxWallTimeMs ?? DEFAULT_MAX_WALL_TIME_MS\n\tconst stopOnPiFailure = options.stopOnPiFailure ?? true\n\tconst interruptRateThreshold = options.interruptRateThreshold ?? null\n\tconst loopId = createLoopId()\n\tconst artifactsDir = options.runOptions.artifactsDir\n\tconst loopDir = join(artifactsDir, \"loops\", loopId)\n\n\tmkdirSync(loopDir, { recursive: true })\n\n\tconst loopStartedAt = Date.now()\n\tconst iterations: LoopIterationResult[] = []\n\tlet finalStopReason: LoopStopReason = \"max-iterations-reached\"\n\n\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\ttype: \"loop_started\",\n\t\tloopId,\n\t\tmaxIterations,\n\t\tmaxWallTimeMs,\n\t\tstopOnPiFailure,\n\t\tcreatedAt: new Date().toISOString(),\n\t})\n\n\tfor (let iteration = 1; iteration <= maxIterations; iteration++) {\n\t\tconst iterationStart = Date.now()\n\n\t\tlet controllerResult: ControllerRunResult\n\t\ttry {\n\t\t\tcontrollerResult = runController(options.runOptions)\n\t\t} catch (error) {\n\t\t\t// If controller fails to run (e.g. lease issue), record and stop\n\t\t\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\t\t\ttype: \"loop_iteration_error\",\n\t\t\t\tloopId,\n\t\t\t\titeration,\n\t\t\t\terror: (error as Error).message,\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t})\n\t\t\tfinalStopReason = \"pi-exit-nonzero\"\n\t\t\tbreak\n\t\t}\n\n\t\tconst iterationElapsedMs = Date.now() - iterationStart\n\t\tconst totalElapsedMs = Date.now() - loopStartedAt\n\t\tconst board = snapshotBoard(artifactsDir)\n\t\tconst metrics = controllerResult.metrics\n\n\t\tconst { stopReason, continueReason } = evaluateStopCondition({\n\t\t\titeration,\n\t\t\tmaxIterations,\n\t\t\telapsedMs: totalElapsedMs,\n\t\t\tmaxWallTimeMs,\n\t\t\tpiExitCode: controllerResult.piInvocation.exitCode,\n\t\t\tstopOnPiFailure,\n\t\t\tboard,\n\t\t\tmetrics,\n\t\t\tinterruptRateThreshold,\n\t\t})\n\n\t\tconst iterationResult: LoopIterationResult = {\n\t\t\titeration,\n\t\t\tcontrollerResult,\n\t\t\tboardSnapshot: board,\n\t\t\tmetrics,\n\t\t\telapsedMs: iterationElapsedMs,\n\t\t\tcontinueReason,\n\t\t\tstopReason,\n\t\t}\n\n\t\titerations.push(iterationResult)\n\n\t\twriteJson(join(loopDir, `iteration-${iteration}.json`), {\n\t\t\titeration,\n\t\t\trunId: controllerResult.runId,\n\t\t\tboardSnapshot: board,\n\t\t\tmetrics,\n\t\t\telapsedMs: iterationElapsedMs,\n\t\t\tcontinueReason,\n\t\t\tstopReason,\n\t\t})\n\n\t\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\t\ttype: \"loop_iteration_completed\",\n\t\t\tloopId,\n\t\t\titeration,\n\t\t\trunId: controllerResult.runId,\n\t\t\tpiExitCode: controllerResult.piInvocation.exitCode,\n\t\t\tstopReason,\n\t\t\tcontinueReason,\n\t\t\tcreatedAt: new Date().toISOString(),\n\t\t})\n\n\t\tif (options.onIterationComplete) {\n\t\t\toptions.onIterationComplete(iterationResult)\n\t\t}\n\n\t\tif (stopReason !== null) {\n\t\t\tfinalStopReason = stopReason\n\t\t\tbreak\n\t\t}\n\t}\n\n\tconst totalElapsedMs = Date.now() - loopStartedAt\n\tconst finalBoard = iterations.length > 0 ? iterations[iterations.length - 1].boardSnapshot : snapshotBoard(artifactsDir)\n\tconst aggregate = aggregateMetrics(iterations)\n\n\tconst loopResult: LoopRunResult = {\n\t\tloopId,\n\t\titerations,\n\t\tstopReason: finalStopReason,\n\t\ttotalIterations: iterations.length,\n\t\ttotalElapsedMs,\n\t\tfinalBoardSnapshot: finalBoard,\n\t\taggregateMetrics: aggregate,\n\t}\n\n\twriteJson(join(loopDir, \"loop-summary.json\"), {\n\t\tloopId,\n\t\tstopReason: finalStopReason,\n\t\ttotalIterations: iterations.length,\n\t\ttotalElapsedMs,\n\t\tfinalBoardSnapshot: finalBoard,\n\t\taggregateMetrics: aggregate,\n\t})\n\n\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\ttype: \"loop_finished\",\n\t\tloopId,\n\t\tstopReason: finalStopReason,\n\t\ttotalIterations: iterations.length,\n\t\ttotalElapsedMs,\n\t\tcreatedAt: new Date().toISOString(),\n\t})\n\n\treturn loopResult\n}\n","import { writeFileSync } from \"node:fs\"\nimport {\n\tappendAgentMessage,\n\tcreateAgentSessionRecord,\n\tcreateAgentState,\n\tgetAgentDir,\n\tgetAgentSessionsDir,\n\tgetLatestAgentSession,\n\treadAgentState,\n\twriteAgentState,\n} from \"./agents.js\"\nimport { createTaskRecord, updateTaskRecordStatus, writeTaskRecord } from \"./tasks.js\"\nimport { assertCommandAvailable, runCommandSync } from \"./shell.js\"\nimport type { AgentSessionRecord, AgentStateSnapshot, TaskRecord } from \"./types.js\"\n\nexport interface SpawnAgentRunOptions {\n\trepoRoot: string\n\tartifactsDir: string\n\trole: string\n\tagentId: string\n\ttask: string | null\n\tappendedSystemPrompt?: string | null\n\textensionPath?: string | null\n\ttaskId?: string | null\n}\n\nexport interface SpawnAgentRunResult {\n\tpiResult: { stdout: string; stderr: string; exitCode: number }\n\tlatestSession: AgentSessionRecord\n\tcompletionMessage: string\n}\n\nexport interface DelegateTaskOptions {\n\trepoRoot: string\n\tartifactsDir: string\n\tfromAgentId: string\n\trole: string\n\tagentId?: string | null\n\tappendedSystemPrompt?: string | null\n\textensionPath?: string | null\n\ttask: string\n}\n\nexport interface DelegateTaskResult {\n\ttask: TaskRecord\n\tagentId: string\n\tpiResult: { stdout: string; stderr: string; exitCode: number }\n\tlatestSession: AgentSessionRecord\n}\n\nexport interface ResolvedAgentSession {\n\tstate: AgentStateSnapshot\n\tsession: AgentSessionRecord\n}\n\nexport interface RunAgentTurnOptions {\n\trepoRoot: string\n\tartifactsDir: string\n\tagentId: string\n\tmessage: string\n\tfrom?: string\n\truntimeArgs?: string[] | null\n}\n\nexport interface RunAgentTurnResult {\n\tpiResult: { stdout: string; stderr: string; exitCode: number }\n\tlatestSession: AgentSessionRecord\n\tcompletionMessage: string\n}\n\nfunction createPiInvocationArgs(input: {\n\tsessionDir?: string | null\n\tsessionPath?: string | null\n\tprompt?: string | null\n\tappendedSystemPrompt?: string | null\n\textensionPath?: string | null\n}): string[] {\n\tconst args: string[] = []\n\n\tif (input.extensionPath) args.push(\"--extension\", input.extensionPath)\n\tif (input.appendedSystemPrompt) args.push(\"--append-system-prompt\", input.appendedSystemPrompt)\n\tif (input.sessionPath) args.push(\"--session\", input.sessionPath)\n\telse if (input.sessionDir) args.push(\"--session-dir\", input.sessionDir)\n\telse throw new Error(\"Pi invocation requires a session path or session directory\")\n\tif (input.prompt) args.push(\"-p\", input.prompt)\n\n\treturn args\n}\n\nexport function createRolePrompt(input: { role: string; task: string | null; repoRoot: string }): string {\n\tconst task = input.task ?? \"pick the next bounded task from the current repo context\"\n\n\tswitch (input.role) {\n\t\tcase \"leader\":\n\t\t\treturn [\n\t\t\t\t\"You are the Pi Town leader.\",\n\t\t\t\t\"You coordinate work for this repository and act as the primary human-facing agent.\",\n\t\t\t\t\"\",\n\t\t\t\t`Repository: ${input.repoRoot}`,\n\t\t\t\t`Task: ${task}`,\n\t\t\t\t\"Keep updates concise, choose bounded next steps, and leave a durable artifact trail.\",\n\t\t\t].join(\"\\n\")\n\t\tcase \"reviewer\":\n\t\t\treturn [\n\t\t\t\t\"You are the Pi Town reviewer.\",\n\t\t\t\t\"You review work for correctness, safety, and completeness.\",\n\t\t\t\t\"\",\n\t\t\t\t`Repository: ${input.repoRoot}`,\n\t\t\t\t`Task: ${task}`,\n\t\t\t\t\"Focus on validation confidence, regressions, and whether the output is ready for a human handoff.\",\n\t\t\t].join(\"\\n\")\n\t\tcase \"docs-keeper\":\n\t\t\treturn [\n\t\t\t\t\"You are the Pi Town docs keeper.\",\n\t\t\t\t\"You summarize outcomes, blockers, and continuity in compact factual language.\",\n\t\t\t\t\"\",\n\t\t\t\t`Repository: ${input.repoRoot}`,\n\t\t\t\t`Task: ${task}`,\n\t\t\t\t\"Keep the output concise and useful for the next run or human review.\",\n\t\t\t].join(\"\\n\")\n\t\tdefault:\n\t\t\treturn [\n\t\t\t\t\"You are the Pi Town worker.\",\n\t\t\t\t\"You implement one bounded task at a time.\",\n\t\t\t\t\"\",\n\t\t\t\t`Repository: ${input.repoRoot}`,\n\t\t\t\t`Task: ${task}`,\n\t\t\t\t\"Keep scope tight, prefer explicit validations, and summarize what changed and what still needs follow-up.\",\n\t\t\t].join(\"\\n\")\n\t}\n}\n\nexport function resolveAgentSession(agentId: string, artifactsDir: string): ResolvedAgentSession {\n\tconst state = readAgentState(artifactsDir, agentId)\n\tif (state === null) throw new Error(`Unknown agent: ${agentId}`)\n\n\tconst latestSession = getLatestAgentSession(artifactsDir, agentId)\n\tconst sessionPath = state.session.sessionPath ?? latestSession.sessionPath\n\tconst sessionId = state.session.sessionId ?? latestSession.sessionId\n\tconst sessionDir = state.session.sessionDir ?? latestSession.sessionDir ?? getAgentSessionsDir(artifactsDir, agentId)\n\n\tif (sessionPath === null) {\n\t\tthrow new Error(`Agent ${agentId} does not have a persisted Pi session yet.`)\n\t}\n\n\treturn {\n\t\tstate,\n\t\tsession: createAgentSessionRecord({\n\t\t\tsessionDir,\n\t\t\tsessionId,\n\t\t\tsessionPath,\n\t\t\tlastAttachedAt: new Date().toISOString(),\n\t\t}),\n\t}\n}\n\nexport function queueAgentMessage(input: { artifactsDir: string; agentId: string; from: string; body: string }) {\n\tconst state = readAgentState(input.artifactsDir, input.agentId)\n\tif (state === null) throw new Error(`Unknown agent: ${input.agentId}`)\n\n\tappendAgentMessage({\n\t\tartifactsDir: input.artifactsDir,\n\t\tagentId: input.agentId,\n\t\tbox: \"inbox\",\n\t\tfrom: input.from,\n\t\tbody: input.body,\n\t})\n\n\twriteAgentState(\n\t\tinput.artifactsDir,\n\t\tcreateAgentState({\n\t\t\t...state,\n\t\t\tstatus: state.status === \"idle\" ? \"queued\" : state.status,\n\t\t\tlastMessage: input.body,\n\t\t\twaitingOn: null,\n\t\t\tblocked: false,\n\t\t\tsession: createAgentSessionRecord({\n\t\t\t\tsessionDir: state.session.sessionDir ?? getAgentSessionsDir(input.artifactsDir, input.agentId),\n\t\t\t\tsessionId: state.session.sessionId,\n\t\t\t\tsessionPath: state.session.sessionPath,\n\t\t\t\tlastAttachedAt: state.session.lastAttachedAt,\n\t\t\t}),\n\t\t}),\n\t)\n}\n\nexport function updateAgentStatus(input: {\n\tartifactsDir: string\n\tagentId: string\n\tstatus: \"queued\" | \"running\" | \"idle\" | \"blocked\" | \"completed\" | \"failed\"\n\tlastMessage?: string | null\n\twaitingOn?: string | null\n\tblocked?: boolean\n}) {\n\tconst state = readAgentState(input.artifactsDir, input.agentId)\n\tif (state === null) throw new Error(`Unknown agent: ${input.agentId}`)\n\n\tif (state.taskId) {\n\t\tconst taskStatus =\n\t\t\tinput.status === \"completed\"\n\t\t\t\t? \"completed\"\n\t\t\t\t: input.status === \"blocked\" || input.status === \"failed\"\n\t\t\t\t\t? \"blocked\"\n\t\t\t\t\t: input.status === \"running\" || input.status === \"queued\"\n\t\t\t\t\t\t? \"running\"\n\t\t\t\t\t\t: null\n\t\tif (taskStatus) updateTaskRecordStatus(input.artifactsDir, state.taskId, taskStatus)\n\t}\n\n\twriteAgentState(\n\t\tinput.artifactsDir,\n\t\tcreateAgentState({\n\t\t\t...state,\n\t\t\tstatus: input.status,\n\t\t\tlastMessage: input.lastMessage ?? state.lastMessage,\n\t\t\twaitingOn: input.waitingOn ?? state.waitingOn,\n\t\t\tblocked: input.blocked ?? state.blocked,\n\t\t\tsession: state.session,\n\t\t}),\n\t)\n}\n\nexport function spawnAgentRun(options: SpawnAgentRunOptions): SpawnAgentRunResult {\n\tconst sessionDir = getAgentSessionsDir(options.artifactsDir, options.agentId)\n\n\tif (readAgentState(options.artifactsDir, options.agentId) !== null) {\n\t\tthrow new Error(`Agent already exists: ${options.agentId}`)\n\t}\n\n\tassertCommandAvailable(\"pi\")\n\n\tconst state = createAgentState({\n\t\tagentId: options.agentId,\n\t\trole: options.role,\n\t\tstatus: \"queued\",\n\t\ttaskId: options.taskId ?? null,\n\t\ttask: options.task,\n\t\tlastMessage: options.task ? `Spawned with task: ${options.task}` : `Spawned ${options.role} agent`,\n\t\tsession: createAgentSessionRecord({\n\t\t\tsessionDir,\n\t\t}),\n\t})\n\twriteAgentState(options.artifactsDir, state)\n\tif (options.task) {\n\t\tappendAgentMessage({\n\t\t\tartifactsDir: options.artifactsDir,\n\t\t\tagentId: options.agentId,\n\t\t\tbox: \"inbox\",\n\t\t\tfrom: \"system\",\n\t\t\tbody: options.task,\n\t\t})\n\t}\n\n\twriteAgentState(\n\t\toptions.artifactsDir,\n\t\tcreateAgentState({\n\t\t\t...state,\n\t\t\tstatus: \"running\",\n\t\t\tlastMessage: options.task ? `Running ${options.role} task: ${options.task}` : `Running ${options.role} agent`,\n\t\t}),\n\t)\n\n\tconst prompt = createRolePrompt({ role: options.role, task: options.task, repoRoot: options.repoRoot })\n\tconst piArgs = createPiInvocationArgs({\n\t\tsessionDir,\n\t\tprompt,\n\t\tappendedSystemPrompt: options.appendedSystemPrompt,\n\t\textensionPath: options.extensionPath,\n\t})\n\tconst piResult = runCommandSync(\"pi\", piArgs, {\n\t\tcwd: options.repoRoot,\n\t\tenv: process.env,\n\t})\n\tconst latestSession = getLatestAgentSession(options.artifactsDir, options.agentId)\n\tconst agentArtifactsDir = getAgentDir(options.artifactsDir, options.agentId)\n\twriteFileSync(`${agentArtifactsDir}/latest-stdout.txt`, piResult.stdout, \"utf-8\")\n\twriteFileSync(`${agentArtifactsDir}/latest-stderr.txt`, piResult.stderr, \"utf-8\")\n\twriteFileSync(\n\t\t`${agentArtifactsDir}/latest-invocation.json`,\n\t\t`${JSON.stringify(\n\t\t\t{\n\t\t\t\tcommand: \"pi\",\n\t\t\t\targs: piArgs,\n\t\t\t\texitCode: piResult.exitCode,\n\t\t\t\tsessionDir,\n\t\t\t\tsessionPath: latestSession.sessionPath,\n\t\t\t\tsessionId: latestSession.sessionId,\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 completionMessage =\n\t\tpiResult.stdout.trim() ||\n\t\t(piResult.exitCode === 0 ? `${options.role} run completed` : `${options.role} run exited with code ${piResult.exitCode}`)\n\tappendAgentMessage({\n\t\tartifactsDir: options.artifactsDir,\n\t\tagentId: options.agentId,\n\t\tbox: \"outbox\",\n\t\tfrom: options.agentId,\n\t\tbody: completionMessage,\n\t})\n\twriteAgentState(\n\t\toptions.artifactsDir,\n\t\tcreateAgentState({\n\t\t\t...state,\n\t\t\tstatus: piResult.exitCode === 0 ? \"idle\" : \"blocked\",\n\t\t\tlastMessage: completionMessage,\n\t\t\tblocked: piResult.exitCode !== 0,\n\t\t\twaitingOn: piResult.exitCode === 0 ? null : \"human-or-follow-up-run\",\n\t\t\tsession: createAgentSessionRecord({\n\t\t\t\tsessionDir: latestSession.sessionDir,\n\t\t\t\tsessionId: latestSession.sessionId,\n\t\t\t\tsessionPath: latestSession.sessionPath,\n\t\t\t}),\n\t\t}),\n\t)\n\n\treturn { piResult, latestSession, completionMessage }\n}\n\nexport function runAgentTurn(options: RunAgentTurnOptions): RunAgentTurnResult {\n\tassertCommandAvailable(\"pi\")\n\n\tconst resolved = resolveAgentSession(options.agentId, options.artifactsDir)\n\tconst messageSource = options.from ?? \"human\"\n\twriteAgentState(\n\t\toptions.artifactsDir,\n\t\tcreateAgentState({\n\t\t\t...resolved.state,\n\t\t\tstatus: \"running\",\n\t\t\tlastMessage: `Responding to ${messageSource}: ${options.message}`,\n\t\t\twaitingOn: null,\n\t\t\tblocked: false,\n\t\t\tsession: resolved.session,\n\t\t}),\n\t)\n\n\tconst piArgs =\n\t\toptions.runtimeArgs && options.runtimeArgs.length > 0\n\t\t\t? options.runtimeArgs\n\t\t\t: createPiInvocationArgs({\n\t\t\t\t\tsessionPath: resolved.session.sessionPath,\n\t\t\t\t\tprompt: options.message,\n\t\t\t\t})\n\tconst piResult = runCommandSync(\"pi\", piArgs, {\n\t\tcwd: options.repoRoot,\n\t\tenv: process.env,\n\t})\n\tconst latestSession = getLatestAgentSession(options.artifactsDir, options.agentId)\n\tconst agentArtifactsDir = getAgentDir(options.artifactsDir, options.agentId)\n\twriteFileSync(`${agentArtifactsDir}/latest-stdout.txt`, piResult.stdout, \"utf-8\")\n\twriteFileSync(`${agentArtifactsDir}/latest-stderr.txt`, piResult.stderr, \"utf-8\")\n\twriteFileSync(\n\t\t`${agentArtifactsDir}/latest-invocation.json`,\n\t\t`${JSON.stringify(\n\t\t\t{\n\t\t\t\tcommand: \"pi\",\n\t\t\t\targs: piArgs,\n\t\t\t\texitCode: piResult.exitCode,\n\t\t\t\tsessionDir: latestSession.sessionDir,\n\t\t\t\tsessionPath: latestSession.sessionPath,\n\t\t\t\tsessionId: latestSession.sessionId,\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 completionMessage =\n\t\tpiResult.stdout.trim() ||\n\t\t(piResult.exitCode === 0\n\t\t\t? `${resolved.state.role} turn completed`\n\t\t\t: `${resolved.state.role} turn exited with code ${piResult.exitCode}`)\n\tappendAgentMessage({\n\t\tartifactsDir: options.artifactsDir,\n\t\tagentId: options.agentId,\n\t\tbox: \"outbox\",\n\t\tfrom: options.agentId,\n\t\tbody: completionMessage,\n\t})\n\n\twriteAgentState(\n\t\toptions.artifactsDir,\n\t\tcreateAgentState({\n\t\t\t...resolved.state,\n\t\t\tstatus: piResult.exitCode === 0 ? \"idle\" : \"blocked\",\n\t\t\tlastMessage: completionMessage,\n\t\t\twaitingOn: piResult.exitCode === 0 ? null : \"human-or-follow-up-run\",\n\t\t\tblocked: piResult.exitCode !== 0,\n\t\t\tsession: createAgentSessionRecord({\n\t\t\t\tsessionDir: latestSession.sessionDir,\n\t\t\t\tsessionId: latestSession.sessionId,\n\t\t\t\tsessionPath: latestSession.sessionPath,\n\t\t\t}),\n\t\t}),\n\t)\n\n\treturn { piResult, latestSession, completionMessage }\n}\n\nexport function delegateTask(options: DelegateTaskOptions): DelegateTaskResult {\n\tconst fromState = readAgentState(options.artifactsDir, options.fromAgentId)\n\tif (fromState === null) throw new Error(`Unknown delegating agent: ${options.fromAgentId}`)\n\n\tconst agentId = options.agentId ?? `${options.role}-${Date.now()}`\n\tconst task = createTaskRecord({\n\t\ttaskId: `task-${Date.now()}`,\n\t\ttitle: options.task,\n\t\tstatus: \"queued\",\n\t\trole: options.role,\n\t\tassignedAgentId: agentId,\n\t\tcreatedBy: options.fromAgentId,\n\t})\n\twriteTaskRecord(options.artifactsDir, task)\n\n\tappendAgentMessage({\n\t\tartifactsDir: options.artifactsDir,\n\t\tagentId: options.fromAgentId,\n\t\tbox: \"outbox\",\n\t\tfrom: options.fromAgentId,\n\t\tbody: `Delegated ${task.taskId} to ${agentId}: ${options.task}`,\n\t})\n\n\tconst { piResult, latestSession } = spawnAgentRun({\n\t\trepoRoot: options.repoRoot,\n\t\tartifactsDir: options.artifactsDir,\n\t\trole: options.role,\n\t\tagentId,\n\t\tappendedSystemPrompt: options.appendedSystemPrompt,\n\t\textensionPath: options.extensionPath,\n\t\ttask: options.task,\n\t\ttaskId: task.taskId,\n\t})\n\n\tappendAgentMessage({\n\t\tartifactsDir: options.artifactsDir,\n\t\tagentId,\n\t\tbox: \"inbox\",\n\t\tfrom: options.fromAgentId,\n\t\tbody: `Delegated by ${options.fromAgentId} as ${task.taskId}: ${options.task}`,\n\t})\n\n\twriteTaskRecord(options.artifactsDir, {\n\t\t...task,\n\t\tstatus: piResult.exitCode === 0 ? \"completed\" : \"blocked\",\n\t\tupdatedAt: new Date().toISOString(),\n\t})\n\n\treturn {\n\t\ttask: {\n\t\t\t...task,\n\t\t\tstatus: piResult.exitCode === 0 ? \"completed\" : \"blocked\",\n\t\t\tupdatedAt: new Date().toISOString(),\n\t\t},\n\t\tagentId,\n\t\tpiResult,\n\t\tlatestSession,\n\t}\n}\n","export function normalizeAgentId(agentId: string): string {\n\treturn agentId === \"mayor\" ? \"leader\" : agentId\n}\n","import { readPiTownMayorPrompt, resolvePiTownExtensionPath } from \"@schilderlabs/pitown-package\"\n\nexport interface PiTownRuntimeArgsOptions {\n\tagentId: string\n\tsessionPath?: string | null\n\tsessionDir?: string | null\n\tprompt?: string | null\n\tmessage?: string | null\n}\n\nexport function isMayorAgent(agentId: string) {\n\treturn agentId === \"leader\" || agentId === \"mayor\"\n}\n\nexport function createPiTownRuntimeArgs(options: PiTownRuntimeArgsOptions): string[] {\n\tconst args = [\"--extension\", resolvePiTownExtensionPath()]\n\n\tif (isMayorAgent(options.agentId)) {\n\t\targs.push(\"--append-system-prompt\", readPiTownMayorPrompt())\n\t}\n\n\tif (options.sessionPath) args.push(\"--session\", options.sessionPath)\n\telse if (options.sessionDir) args.push(\"--session-dir\", options.sessionDir)\n\telse throw new Error(\"Pi Town runtime requires either a session path or a session directory\")\n\n\tif (options.prompt) args.push(\"-p\", options.prompt)\n\tif (options.message) args.push(options.message)\n\n\treturn args\n}\n","import { existsSync, readFileSync } from \"node:fs\"\nimport { createRepoSlug, getRepoIdentity, getRepoRoot, isGitRepo } from \"../../core/src/index.js\"\nimport { parseOptionalRepoFlag } from \"./config.js\"\nimport { getLatestRunPointerPath, getRepoArtifactsDir } from \"./paths.js\"\n\ninterface LatestRunPointer {\n\trepoSlug: string\n\trepoRoot: string\n}\n\nexport interface ResolvedRepoContext {\n\trepoRoot: string\n\trepoSlug: string\n\tartifactsDir: string\n\trest: string[]\n}\n\nexport function resolveRepoContext(argv: string[]): ResolvedRepoContext {\n\tconst { repo, rest } = parseOptionalRepoFlag(argv)\n\n\tif (repo) {\n\t\tconst repoRoot = getRepoRoot(repo)\n\t\tconst repoSlug = createRepoSlug(getRepoIdentity(repoRoot), repoRoot)\n\t\treturn {\n\t\t\trepoRoot,\n\t\t\trepoSlug,\n\t\t\tartifactsDir: getRepoArtifactsDir(repoSlug),\n\t\t\trest,\n\t\t}\n\t}\n\n\tconst cwd = process.cwd()\n\tconst repoRoot = getRepoRoot(cwd)\n\tconst repoSlug = createRepoSlug(getRepoIdentity(repoRoot), repoRoot)\n\tconst artifactsDir = getRepoArtifactsDir(repoSlug)\n\tif (isGitRepo(cwd) || existsSync(artifactsDir)) {\n\t\treturn {\n\t\t\trepoRoot,\n\t\t\trepoSlug,\n\t\t\tartifactsDir,\n\t\t\trest,\n\t\t}\n\t}\n\n\tconst latestPointerPath = getLatestRunPointerPath()\n\tif (!existsSync(latestPointerPath)) {\n\t\treturn {\n\t\t\trepoRoot,\n\t\t\trepoSlug,\n\t\t\tartifactsDir,\n\t\t\trest,\n\t\t}\n\t}\n\n\tconst latest = JSON.parse(readFileSync(latestPointerPath, \"utf-8\")) as LatestRunPointer\n\treturn {\n\t\trepoRoot: latest.repoRoot,\n\t\trepoSlug: latest.repoSlug,\n\t\tartifactsDir: getRepoArtifactsDir(latest.repoSlug),\n\t\trest,\n\t}\n}\n","import {\n\tassertCommandAvailable,\n\tresolveAgentSession,\n\trunCommandInteractive,\n\twriteAgentState,\n} from \"../../core/src/index.js\"\nimport { normalizeAgentId } from \"./agent-id.js\"\nimport { createPiTownRuntimeArgs } from \"./pi-runtime.js\"\nimport { resolveRepoContext } from \"./repo-context.js\"\n\nexport function attachTownAgent(argv = process.argv.slice(2)) {\n\tconst repo = resolveRepoContext(argv)\n\tconst [agentArg] = repo.rest\n\tif (!agentArg) throw new Error(\"Usage: pitown attach [--repo <path>] <agent>\")\n\tconst agentId = normalizeAgentId(agentArg)\n\n\tassertCommandAvailable(\"pi\")\n\tconst resolved = resolveAgentSession(agentId, repo.artifactsDir)\n\twriteAgentState(repo.artifactsDir, { ...resolved.state, session: resolved.session })\n\n\tconsole.log(\"[pitown] attach\")\n\tconsole.log(`- repo root: ${repo.repoRoot}`)\n\tconsole.log(`- agent: ${agentId}`)\n\tconsole.log(`- session: ${resolved.session.sessionPath}`)\n\n\tconst exitCode = runCommandInteractive(\n\t\t\"pi\",\n\t\tcreatePiTownRuntimeArgs({\n\t\t\tagentId,\n\t\t\tsessionPath: resolved.session.sessionPath,\n\t\t}),\n\t\t{\n\t\t\tcwd: repo.repoRoot,\n\t\t\tenv: process.env,\n\t\t},\n\t)\n\tif (exitCode !== 0) process.exitCode = exitCode\n}\n","import { listAgentStates } from \"../../core/src/index.js\"\nimport { getRepoAgentsDir } from \"./paths.js\"\nimport { resolveRepoContext } from \"./repo-context.js\"\n\nexport function showTownBoard(argv = process.argv.slice(2)) {\n\tconst repo = resolveRepoContext(argv)\n\tconst agents = listAgentStates(repo.artifactsDir)\n\n\tconsole.log(\"[pitown] board\")\n\tconsole.log(`- repo root: ${repo.repoRoot}`)\n\tconsole.log(`- agents dir: ${getRepoAgentsDir(repo.repoSlug)}`)\n\n\tif (agents.length === 0) {\n\t\tconsole.log(\"- no agents found yet\")\n\t\treturn\n\t}\n\n\tfor (const agent of agents) {\n\t\tconst task = agent.task ?? \"no active task\"\n\t\tconst note = agent.lastMessage ? ` | ${agent.lastMessage}` : \"\"\n\t\tconst waitingOn = agent.waitingOn ? ` | waiting on: ${agent.waitingOn}` : \"\"\n\t\tconst taskId = agent.taskId ? ` [${agent.taskId}]` : \"\"\n\t\tconsole.log(`${agent.agentId.padEnd(12)} ${agent.status.padEnd(8)} ${task}${taskId}${note}${waitingOn}`)\n\t}\n}\n","import {\n\tassertCommandAvailable,\n\tresolveAgentSession,\n\trunCommandInteractive,\n\twriteAgentState,\n} from \"../../core/src/index.js\"\nimport { normalizeAgentId } from \"./agent-id.js\"\nimport { createPiTownRuntimeArgs } from \"./pi-runtime.js\"\nimport { resolveRepoContext } from \"./repo-context.js\"\n\nexport function continueTownAgent(argv = process.argv.slice(2)) {\n\tconst repo = resolveRepoContext(argv)\n\tconst [agentArg, ...messageParts] = repo.rest\n\tif (!agentArg) throw new Error('Usage: pitown continue [--repo <path>] <agent> [\"message\"]')\n\tconst agentId = normalizeAgentId(agentArg)\n\n\tassertCommandAvailable(\"pi\")\n\tconst resolved = resolveAgentSession(agentId, repo.artifactsDir)\n\twriteAgentState(repo.artifactsDir, { ...resolved.state, session: resolved.session })\n\n\tconst message = messageParts.join(\" \").trim()\n\tconst args = createPiTownRuntimeArgs({\n\t\tagentId,\n\t\tsessionPath: resolved.session.sessionPath,\n\t\tmessage: message || null,\n\t})\n\n\tconsole.log(\"[pitown] continue\")\n\tconsole.log(`- repo root: ${repo.repoRoot}`)\n\tconsole.log(`- agent: ${agentId}`)\n\tconsole.log(`- session: ${resolved.session.sessionPath}`)\n\tif (message) console.log(`- message: ${message}`)\n\n\tconst exitCode = runCommandInteractive(\"pi\", args, {\n\t\tcwd: repo.repoRoot,\n\t\tenv: process.env,\n\t})\n\tif (exitCode !== 0) process.exitCode = exitCode\n}\n","import {\n\tdelegateTask,\n\treadAgentState,\n} from \"../../core/src/index.js\"\nimport { resolvePiTownExtensionPath } from \"@schilderlabs/pitown-package\"\nimport { normalizeAgentId } from \"./agent-id.js\"\nimport { resolveRepoContext } from \"./repo-context.js\"\n\ninterface DelegateFlags {\n\tfrom: string\n\trole: string\n\tagentId: string | null\n\ttask: string | null\n}\n\nfunction parseDelegateFlags(argv: string[]): DelegateFlags {\n\tlet from = \"leader\"\n\tlet role = \"worker\"\n\tlet agentId: string | null = null\n\tlet task: string | null = null\n\n\tfor (let index = 0; index < argv.length; index += 1) {\n\t\tconst arg = argv[index]\n\n\t\tif (arg.startsWith(\"--from=\")) {\n\t\t\tfrom = arg.slice(\"--from=\".length)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--from\") {\n\t\t\tfrom = argv[index + 1] ?? from\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\t\tif (arg.startsWith(\"--role=\")) {\n\t\t\trole = arg.slice(\"--role=\".length)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--role\") {\n\t\t\trole = argv[index + 1] ?? role\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\t\tif (arg.startsWith(\"--agent=\")) {\n\t\t\tagentId = arg.slice(\"--agent=\".length)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--agent\") {\n\t\t\tagentId = argv[index + 1] ?? null\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\t\tif (arg.startsWith(\"--task=\")) {\n\t\t\ttask = arg.slice(\"--task=\".length)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--task\") {\n\t\t\ttask = argv[index + 1] ?? null\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tthrow new Error(`Unknown argument: ${arg}`)\n\t}\n\n\tif (!task) {\n\t\tthrow new Error(\"Usage: pitown delegate [--repo <path>] [--from <agent>] [--role <role>] [--agent <id>] --task <text>\")\n\t}\n\n\treturn { from, role, agentId, task }\n}\n\nexport function delegateTownTask(argv = process.argv.slice(2)) {\n\tconst repo = resolveRepoContext(argv)\n\tconst flags = parseDelegateFlags(repo.rest)\n\tconst fromAgentId = normalizeAgentId(flags.from)\n\tconst fromState = readAgentState(repo.artifactsDir, fromAgentId)\n\tif (fromState === null) throw new Error(`Unknown delegating agent: ${fromAgentId}`)\n\n\tconst { agentId, latestSession, piResult, task } = delegateTask({\n\t\trepoRoot: repo.repoRoot,\n\t\tartifactsDir: repo.artifactsDir,\n\t\tfromAgentId: fromAgentId,\n\t\trole: flags.role,\n\t\tagentId: flags.agentId,\n\t\ttask: flags.task,\n\t\textensionPath: resolvePiTownExtensionPath(),\n\t})\n\n\tconsole.log(\"[pitown] delegate\")\n\tconsole.log(`- repo root: ${repo.repoRoot}`)\n\tconsole.log(`- from: ${fromAgentId}`)\n\tconsole.log(`- task id: ${task.taskId}`)\n\tconsole.log(`- agent: ${agentId}`)\n\tconsole.log(`- role: ${flags.role}`)\n\tconsole.log(`- pi exit code: ${piResult.exitCode}`)\n\tif (latestSession.sessionPath) console.log(`- session: ${latestSession.sessionPath}`)\n}\n","import { existsSync, readFileSync } from \"node:fs\"\nimport { dirname, isAbsolute, resolve } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { getUserConfigPath } from \"./paths.js\"\n\nconst DEFAULT_GOAL = \"continue from current scaffold state\"\nconst DEFAULT_MAX_ITERATIONS = 10\nconst DEFAULT_MAX_TIME_MINUTES = 60\n\ninterface UserConfig {\n\trepo?: string\n\tplan?: string\n\tgoal?: string\n}\n\nexport interface ResolvedLoopConfig {\n\trepo: string\n\tplan: string | null\n\tgoal: string\n\tmaxIterations: number\n\tmaxTimeMinutes: number\n\tstopOnPiFailure: boolean\n}\n\ninterface LoopCliFlags {\n\trepo?: string\n\tplan?: string\n\tgoal?: string\n\tmaxIterations?: number\n\tmaxTime?: number\n\tnoStopOnFailure: boolean\n}\n\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir()\n\tif (value.startsWith(\"~/\")) return resolve(homedir(), value.slice(2))\n\treturn value\n}\n\nfunction resolvePathValue(value: string | undefined, baseDir: string): string | undefined {\n\tif (!value) return undefined\n\tconst expanded = expandHome(value)\n\treturn isAbsolute(expanded) ? resolve(expanded) : resolve(baseDir, expanded)\n}\n\nfunction parseLoopCliFlags(argv: string[]): LoopCliFlags {\n\tconst flags: LoopCliFlags = { noStopOnFailure: false }\n\n\tfor (let index = 0; index < argv.length; index += 1) {\n\t\tconst arg = argv[index]\n\n\t\tif (arg.startsWith(\"--repo=\")) {\n\t\t\tflags.repo = arg.slice(\"--repo=\".length)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--repo\") {\n\t\t\tconst value = argv[index + 1]\n\t\t\tif (!value) throw new Error(\"Missing value for --repo\")\n\t\t\tflags.repo = value\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--plan=\")) {\n\t\t\tflags.plan = arg.slice(\"--plan=\".length)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--plan\") {\n\t\t\tconst value = argv[index + 1]\n\t\t\tif (!value) throw new Error(\"Missing value for --plan\")\n\t\t\tflags.plan = value\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--goal=\")) {\n\t\t\tflags.goal = arg.slice(\"--goal=\".length)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--goal\") {\n\t\t\tconst value = argv[index + 1]\n\t\t\tif (!value) throw new Error(\"Missing value for --goal\")\n\t\t\tflags.goal = value\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--max-iterations=\")) {\n\t\t\tflags.maxIterations = Number.parseInt(arg.slice(\"--max-iterations=\".length), 10)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--max-iterations\") {\n\t\t\tconst value = argv[index + 1]\n\t\t\tif (!value) throw new Error(\"Missing value for --max-iterations\")\n\t\t\tflags.maxIterations = Number.parseInt(value, 10)\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--max-time=\")) {\n\t\t\tflags.maxTime = Number.parseInt(arg.slice(\"--max-time=\".length), 10)\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--max-time\") {\n\t\t\tconst value = argv[index + 1]\n\t\t\tif (!value) throw new Error(\"Missing value for --max-time\")\n\t\t\tflags.maxTime = Number.parseInt(value, 10)\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg === \"--no-stop-on-failure\") {\n\t\t\tflags.noStopOnFailure = true\n\t\t\tcontinue\n\t\t}\n\n\t\tthrow new Error(`Unknown argument: ${arg}`)\n\t}\n\n\treturn flags\n}\n\nfunction loadUserConfig(): UserConfig {\n\tconst configPath = getUserConfigPath()\n\tif (!existsSync(configPath)) return {}\n\treturn JSON.parse(readFileSync(configPath, \"utf-8\")) as UserConfig\n}\n\nexport function resolveLoopConfig(argv: string[]): ResolvedLoopConfig {\n\tconst flags = parseLoopCliFlags(argv)\n\tconst configPath = getUserConfigPath()\n\tconst userConfig = loadUserConfig()\n\tconst configDir = dirname(configPath)\n\n\tconst repo =\n\t\tresolvePathValue(flags.repo, process.cwd()) ??\n\t\tresolvePathValue(userConfig.repo, configDir) ??\n\t\tresolve(process.cwd())\n\tconst plan = resolvePathValue(flags.plan, process.cwd()) ?? resolvePathValue(userConfig.plan, configDir) ?? null\n\tconst goal = flags.goal ?? userConfig.goal ?? DEFAULT_GOAL\n\n\treturn {\n\t\trepo,\n\t\tplan,\n\t\tgoal,\n\t\tmaxIterations: flags.maxIterations ?? DEFAULT_MAX_ITERATIONS,\n\t\tmaxTimeMinutes: flags.maxTime ?? DEFAULT_MAX_TIME_MINUTES,\n\t\tstopOnPiFailure: !flags.noStopOnFailure,\n\t}\n}\n","import { existsSync, mkdirSync, statSync } from \"node:fs\"\nimport { readPiTownMayorPrompt, resolvePiTownExtensionPath } from \"@schilderlabs/pitown-package\"\nimport {\n\tcreateRepoSlug,\n\tgetRepoIdentity,\n\tgetRepoRoot,\n\trunLoop,\n\ttype LoopRunResult,\n} from \"../../core/src/index.js\"\nimport { resolveLoopConfig } from \"./loop-config.js\"\nimport {\n\tgetRecommendedPlanDir,\n\tgetRepoArtifactsDir,\n\tgetTownHomeDir,\n} from \"./paths.js\"\n\nfunction assertDirectory(path: string, label: string) {\n\tif (!existsSync(path)) throw new Error(`${label} does not exist: ${path}`)\n\tif (!statSync(path).isDirectory()) throw new Error(`${label} is not a directory: ${path}`)\n}\n\nfunction formatMs(ms: number): string {\n\tif (ms < 1000) return `${ms}ms`\n\treturn `${(ms / 1000).toFixed(1)}s`\n}\n\nexport function loopTown(argv = process.argv.slice(2)): LoopRunResult {\n\tconst config = resolveLoopConfig(argv)\n\tassertDirectory(config.repo, \"Target repo\")\n\tif (config.plan) assertDirectory(config.plan, \"Plan path\")\n\n\tconst townHome = getTownHomeDir()\n\tmkdirSync(townHome, { recursive: true })\n\n\tconst repoRoot = getRepoRoot(config.repo)\n\tconst repoId = getRepoIdentity(repoRoot)\n\tconst repoSlug = createRepoSlug(repoId, repoRoot)\n\tconst recommendedPlanDir = config.plan ? null : getRecommendedPlanDir(repoSlug)\n\tconst artifactsDir = getRepoArtifactsDir(repoSlug)\n\n\tconsole.log(`[pitown-loop] starting loop (max ${config.maxIterations} iterations, ${config.maxTimeMinutes}min wall time)`)\n\n\tconst result = runLoop({\n\t\trunOptions: {\n\t\t\tartifactsDir,\n\t\t\tcwd: repoRoot,\n\t\t\tgoal: config.goal,\n\t\t\tmode: \"single-pi\",\n\t\t\tplanPath: config.plan,\n\t\t\trecommendedPlanDir,\n\t\t\tappendedSystemPrompt: readPiTownMayorPrompt(),\n\t\t\textensionPath: resolvePiTownExtensionPath(),\n\t\t},\n\t\tmaxIterations: config.maxIterations,\n\t\tmaxWallTimeMs: config.maxTimeMinutes * 60_000,\n\t\tstopOnPiFailure: config.stopOnPiFailure,\n\t\tonIterationComplete(iteration) {\n\t\t\tconst board = iteration.boardSnapshot\n\t\t\tconst taskSummary = board.tasks.length > 0\n\t\t\t\t? `${board.tasks.length} tasks (${board.tasks.filter((t) => t.status === \"completed\").length} completed, ${board.tasks.filter((t) => t.status === \"running\").length} running)`\n\t\t\t\t: \"no tasks tracked\"\n\t\t\tconst leaderStatus = board.agents.find((a) => a.agentId === \"leader\")?.status ?? \"unknown\"\n\n\t\t\tconsole.log(`[pitown-loop] iteration ${iteration.iteration}/${config.maxIterations} completed (${formatMs(iteration.elapsedMs)})`)\n\t\t\tconsole.log(` - pi exit code: ${iteration.controllerResult.piInvocation.exitCode}`)\n\t\t\tconsole.log(` - run: ${iteration.controllerResult.runId}`)\n\t\t\tconsole.log(` - board: ${taskSummary}, leader ${leaderStatus}`)\n\t\t\tconsole.log(` - metrics: interrupt rate ${iteration.metrics.interruptRate}, autonomous completion ${iteration.metrics.autonomousCompletionRate}`)\n\t\t\tif (iteration.stopReason) {\n\t\t\t\tconsole.log(` - stopping: ${iteration.stopReason}`)\n\t\t\t} else {\n\t\t\t\tconsole.log(` - continuing: ${iteration.continueReason}`)\n\t\t\t}\n\t\t},\n\t})\n\n\tconsole.log(`[pitown-loop] stopped after ${result.totalIterations} iteration${result.totalIterations === 1 ? \"\" : \"s\"} (${formatMs(result.totalElapsedMs)} total)`)\n\tconsole.log(` - reason: ${result.stopReason}`)\n\tconsole.log(` - aggregate metrics: interrupt rate ${result.aggregateMetrics.interruptRate}, autonomous completion ${result.aggregateMetrics.autonomousCompletionRate}`)\n\n\treturn result\n}\n","import {\n\tassertCommandAvailable,\n\tcreateAgentSessionRecord,\n\tcreateAgentState,\n\tgetAgentSessionsDir,\n\tgetLatestAgentSession,\n\treadAgentState,\n\trunCommandInteractive,\n\twriteAgentState,\n} from \"../../core/src/index.js\"\nimport { attachTownAgent } from \"./attach.js\"\nimport { continueTownAgent } from \"./continue.js\"\nimport { createPiTownRuntimeArgs } from \"./pi-runtime.js\"\nimport { resolveRepoContext } from \"./repo-context.js\"\nimport { runTown } from \"./run.js\"\n\nfunction startFreshMayorSession(repoRoot: string, artifactsDir: string) {\n\tconst sessionDir = getAgentSessionsDir(artifactsDir, \"leader\")\n\twriteAgentState(\n\t\tartifactsDir,\n\t\tcreateAgentState({\n\t\t\tagentId: \"leader\",\n\t\t\trole: \"leader\",\n\t\t\tstatus: \"running\",\n\t\t\ttask: \"open the mayor session and plan the next steps for this repository\",\n\t\t\tlastMessage: \"Mayor session opened\",\n\t\t\tsession: createAgentSessionRecord({\n\t\t\t\tsessionDir,\n\t\t\t}),\n\t\t}),\n\t)\n\n\tconsole.log(\"[pitown] mayor\")\n\tconsole.log(`- repo root: ${repoRoot}`)\n\tconsole.log(\"- starting a new mayor session\")\n\n\tconst exitCode = runCommandInteractive(\n\t\t\"pi\",\n\t\tcreatePiTownRuntimeArgs({\n\t\t\tagentId: \"leader\",\n\t\t\tsessionDir,\n\t\t}),\n\t\t{\n\t\t\tcwd: repoRoot,\n\t\t\tenv: process.env,\n\t\t},\n\t)\n\tconst latestSession = getLatestAgentSession(artifactsDir, \"leader\")\n\tconst previousState = readAgentState(artifactsDir, \"leader\")\n\tif (previousState !== null) {\n\t\twriteAgentState(\n\t\t\tartifactsDir,\n\t\t\tcreateAgentState({\n\t\t\t\t...previousState,\n\t\t\t\tstatus: exitCode === 0 ? \"idle\" : \"blocked\",\n\t\t\t\tlastMessage: exitCode === 0 ? \"Mayor session closed\" : `Mayor session exited with code ${exitCode}`,\n\t\t\t\tblocked: exitCode !== 0,\n\t\t\t\twaitingOn: exitCode === 0 ? null : \"human-or-follow-up-run\",\n\t\t\t\tsession: createAgentSessionRecord({\n\t\t\t\t\tsessionDir: latestSession.sessionDir,\n\t\t\t\t\tsessionId: latestSession.sessionId,\n\t\t\t\t\tsessionPath: latestSession.sessionPath,\n\t\t\t\t}),\n\t\t\t}),\n\t\t)\n\t}\n\n\tif (exitCode !== 0) process.exitCode = exitCode\n}\n\nexport function openTownMayor(argv = process.argv.slice(2)) {\n\tconst repo = resolveRepoContext(argv)\n\tconst message = repo.rest.join(\" \").trim()\n\tconst mayorState = readAgentState(repo.artifactsDir, \"leader\")\n\n\tif (mayorState === null) {\n\t\tassertCommandAvailable(\"pi\")\n\t\tif (message) {\n\t\t\trunTown([\"--repo\", repo.repoRoot, \"--goal\", message])\n\t\t\treturn\n\t\t}\n\t\tstartFreshMayorSession(repo.repoRoot, repo.artifactsDir)\n\t\treturn\n\t}\n\n\tif (message) {\n\t\tcontinueTownAgent([\"--repo\", repo.repoRoot, \"mayor\", message])\n\t\treturn\n\t}\n\n\tattachTownAgent([\"--repo\", repo.repoRoot, \"mayor\"])\n}\n","import {\n\tqueueAgentMessage,\n\treadAgentState,\n\trunAgentTurn,\n} from \"../../core/src/index.js\"\nimport { normalizeAgentId } from \"./agent-id.js\"\nimport { createPiTownRuntimeArgs } from \"./pi-runtime.js\"\nimport { resolveRepoContext } from \"./repo-context.js\"\n\nexport function messageTownAgent(argv = process.argv.slice(2)) {\n\tconst repo = resolveRepoContext(argv)\n\tconst [agentArg, ...messageParts] = repo.rest\n\tif (!agentArg || messageParts.length === 0) throw new Error('Usage: pitown msg [--repo <path>] <agent> \"message\"')\n\tconst agentId = normalizeAgentId(agentArg)\n\n\tconst state = readAgentState(repo.artifactsDir, agentId)\n\tif (state === null) throw new Error(`Unknown agent: ${agentId}`)\n\n\tconst body = messageParts.join(\" \").trim()\n\tqueueAgentMessage({ artifactsDir: repo.artifactsDir, agentId, from: \"human\", body })\n\n\tconst deliveredResult =\n\t\tstate.role === \"leader\"\n\t\t\t? runAgentTurn({\n\t\t\t\t\trepoRoot: repo.repoRoot,\n\t\t\t\t\tartifactsDir: repo.artifactsDir,\n\t\t\t\t\tagentId,\n\t\t\t\t\tmessage: body,\n\t\t\t\t\tfrom: \"human\",\n\t\t\t\t\truntimeArgs: createPiTownRuntimeArgs({\n\t\t\t\t\t\tagentId,\n\t\t\t\t\t\tsessionPath: state.session.sessionPath,\n\t\t\t\t\t\tprompt: body,\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t: null\n\n\tconsole.log(\"[pitown] msg\")\n\tconsole.log(`- repo root: ${repo.repoRoot}`)\n\tconsole.log(`- agent: ${agentId}`)\n\tconsole.log(`- queued message: ${body}`)\n\tif (deliveredResult) {\n\t\tconsole.log(`- delivered to session: ${deliveredResult.latestSession.sessionPath}`)\n\t\tconsole.log(`- leader response: ${deliveredResult.completionMessage}`)\n\t}\n}\n","import { readAgentMessages, readAgentState } from \"../../core/src/index.js\"\nimport { normalizeAgentId } from \"./agent-id.js\"\nimport { resolveRepoContext } from \"./repo-context.js\"\n\nfunction printMessages(label: string, lines: { from: string; body: string; createdAt: string }[]) {\n\tconsole.log(`- ${label}:`)\n\tif (lines.length === 0) {\n\t\tconsole.log(\" (empty)\")\n\t\treturn\n\t}\n\n\tfor (const line of lines) {\n\t\tconsole.log(` ${line.createdAt} ${line.from}: ${line.body}`)\n\t}\n}\n\nexport function peekTownAgent(argv = process.argv.slice(2)) {\n\tconst repo = resolveRepoContext(argv)\n\tconst [agentArg] = repo.rest\n\tconst agentId = normalizeAgentId(agentArg ?? \"mayor\")\n\n\tconst state = readAgentState(repo.artifactsDir, agentId)\n\tif (state === null) throw new Error(`Unknown agent: ${agentId}`)\n\n\tconsole.log(\"[pitown] peek\")\n\tconsole.log(`- repo root: ${repo.repoRoot}`)\n\tconsole.log(`- agent: ${state.agentId}`)\n\tconsole.log(`- role: ${state.role}`)\n\tconsole.log(`- status: ${state.status}`)\n\tif (state.taskId) console.log(`- task id: ${state.taskId}`)\n\tif (state.task) console.log(`- task: ${state.task}`)\n\tif (state.branch) console.log(`- branch: ${state.branch}`)\n\tconsole.log(`- blocked: ${state.blocked}`)\n\tif (state.waitingOn) console.log(`- waiting on: ${state.waitingOn}`)\n\tif (state.lastMessage) console.log(`- last message: ${state.lastMessage}`)\n\tif (state.session.sessionId) console.log(`- session id: ${state.session.sessionId}`)\n\tif (state.session.sessionPath) console.log(`- session path: ${state.session.sessionPath}`)\n\tconsole.log(`- updated at: ${state.updatedAt}`)\n\n\tprintMessages(\"recent inbox\", readAgentMessages(repo.artifactsDir, agentId, \"inbox\").slice(-5))\n\tprintMessages(\"recent outbox\", readAgentMessages(repo.artifactsDir, agentId, \"outbox\").slice(-5))\n}\n","import { spawnAgentRun } from \"../../core/src/index.js\"\nimport { resolvePiTownExtensionPath } from \"@schilderlabs/pitown-package\"\nimport { resolveRepoContext } from \"./repo-context.js\"\n\ninterface SpawnFlags {\n\trole: string\n\tagentId: string | null\n\ttask: string | null\n}\n\nexport interface SpawnAgentOptions {\n\trepoRoot: string\n\tartifactsDir: string\n\trole: string\n\tagentId: string\n\ttask: string | null\n\ttaskId?: string | null\n}\n\nfunction parseSpawnFlags(argv: string[]): SpawnFlags {\n\tlet role: string | null = null\n\tlet agentId: string | null = null\n\tlet task: string | null = null\n\n\tfor (let index = 0; index < argv.length; index += 1) {\n\t\tconst arg = argv[index]\n\n\t\tif (arg.startsWith(\"--role=\")) {\n\t\t\trole = arg.slice(\"--role=\".length)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg === \"--role\") {\n\t\t\trole = argv[index + 1] ?? null\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--agent=\")) {\n\t\t\tagentId = arg.slice(\"--agent=\".length)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg === \"--agent\") {\n\t\t\tagentId = argv[index + 1] ?? null\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--task=\")) {\n\t\t\ttask = arg.slice(\"--task=\".length)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg === \"--task\") {\n\t\t\ttask = argv[index + 1] ?? null\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tthrow new Error(`Unknown argument: ${arg}`)\n\t}\n\n\tif (!role) throw new Error(\"Usage: pitown spawn [--repo <path>] --role <role> [--agent <id>] [--task <text>]\")\n\treturn { role, agentId, task }\n}\n\nexport function spawnAgent(options: SpawnAgentOptions) {\n\treturn spawnAgentRun(options)\n}\n\nexport function spawnTownAgent(argv = process.argv.slice(2)) {\n\tconst repo = resolveRepoContext(argv)\n\tconst flags = parseSpawnFlags(repo.rest)\n\tconst agentId = flags.agentId ?? `${flags.role}-${Date.now()}`\n\tconst task = flags.task\n\tconst { piResult, latestSession } = spawnAgent({\n\t\trepoRoot: repo.repoRoot,\n\t\tartifactsDir: repo.artifactsDir,\n\t\trole: flags.role,\n\t\tagentId,\n\t\ttask,\n\t\textensionPath: resolvePiTownExtensionPath(),\n\t})\n\n\tconsole.log(\"[pitown] spawn\")\n\tconsole.log(`- repo root: ${repo.repoRoot}`)\n\tconsole.log(`- agent: ${agentId}`)\n\tconsole.log(`- role: ${flags.role}`)\n\tconsole.log(`- pi exit code: ${piResult.exitCode}`)\n\tif (task) console.log(`- task: ${task}`)\n\tif (latestSession.sessionPath) console.log(`- session: ${latestSession.sessionPath}`)\n}\n","","import packageJson from \"../package.json\" with { type: \"json\" }\n\nexport const CLI_VERSION = packageJson.version\n","#!/usr/bin/env node\n\nimport { attachTownAgent } from \"./attach.js\"\nimport { showTownBoard } from \"./board.js\"\nimport { continueTownAgent } from \"./continue.js\"\nimport { delegateTownTask } from \"./delegate.js\"\nimport { runDoctor } from \"./doctor.js\"\nimport { isDirectExecution } from \"./entrypoint.js\"\nimport { loopTown } from \"./loop.js\"\nimport { openTownMayor } from \"./mayor.js\"\nimport { messageTownAgent } from \"./msg.js\"\nimport { peekTownAgent } from \"./peek.js\"\nimport { runTown } from \"./run.js\"\nimport { spawnTownAgent } from \"./spawn.js\"\nimport { showTownStatus } from \"./status.js\"\nimport { CLI_VERSION } from \"./version.js\"\nimport { watchTown } from \"./watch.js\"\n\nexport function printHelp(showAdvanced = false) {\n\tconsole.log(\n\t\t[\n\t\t\t\"pitown\",\n\t\t\t\"\",\n\t\t\t\"Usage:\",\n\t\t\t\" pitown\",\n\t\t\t' pitown mayor [--repo <path>] [\"message\"]',\n\t\t\t\" pitown board [--repo <path>]\",\n\t\t\t\" pitown peek [--repo <path>] [agent]\",\n\t\t\t' pitown msg [--repo <path>] mayor \"message\"',\n\t\t\t\" pitown status [--repo <path>]\",\n\t\t\t\" pitown doctor\",\n\t\t\t\" pitown help\",\n\t\t\t\" pitown help --all\",\n\t\t\t\" pitown --help\",\n\t\t\t\" pitown -v\",\n\t\t\t\" pitown --version\",\n\t\t\t\"\",\n\t\t\t\"Mayor workflow:\",\n\t\t\t\" pitown\",\n\t\t\t\" pitown mayor\",\n\t\t\t' pitown mayor \"plan the next milestones\"',\n\t\t\t\" /plan\",\n\t\t\t\" /todos\",\n\t\t\t\"\",\n\t\t\t\"Inside the mayor session, `/plan` toggles read-only planning mode and `/todos` shows the captured plan.\",\n\t\t\t\"\",\n\t\t\t\"If --repo is omitted, Pi Town uses the repo for the current working directory when possible.\",\n\t\t\t...(showAdvanced\n\t\t\t\t? [\n\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\"Advanced commands:\",\n\t\t\t\t\t\t\" pitown run [--repo <path>] [--plan <path>] [--goal <text>]\",\n\t\t\t\t\t\t\" pitown loop [--repo <path>] [--plan <path>] [--goal <text>] [--max-iterations N] [--max-time M] [--no-stop-on-failure]\",\n\t\t\t\t\t\t\" pitown attach [--repo <path>] <agent>\",\n\t\t\t\t\t\t' pitown continue [--repo <path>] <agent> [\"message\"]',\n\t\t\t\t\t\t\" pitown delegate [--repo <path>] [--from <agent>] [--role <role>] [--agent <id>] --task <text>\",\n\t\t\t\t\t\t\" pitown spawn [--repo <path>] --role <role> [--agent <id>] [--task <text>]\",\n\t\t\t\t\t\t\" pitown watch [--repo <path>]\",\n\t\t\t\t\t]\n\t\t\t\t: []),\n\t\t].join(\"\\n\"),\n\t)\n}\n\nexport function runCli(argv = process.argv.slice(2)) {\n\tconst [command, ...args] = argv\n\tconst showAdvancedHelp = args.includes(\"--all\")\n\n\tswitch (command) {\n\t\tcase undefined:\n\t\t\topenTownMayor([])\n\t\t\tbreak\n\t\tcase \"help\":\n\t\tcase \"--help\":\n\t\tcase \"-h\":\n\t\t\tprintHelp(showAdvancedHelp)\n\t\t\tbreak\n\t\tcase \"-v\":\n\t\tcase \"--version\":\n\t\tcase \"version\":\n\t\t\tconsole.log(CLI_VERSION)\n\t\t\tbreak\n\t\tcase \"run\": {\n\t\t\tconst result = runTown(args)\n\t\t\tif (result.piInvocation.exitCode !== 0) process.exitCode = result.piInvocation.exitCode\n\t\t\tbreak\n\t\t}\n\t\tcase \"loop\": {\n\t\t\tconst result = loopTown(args)\n\t\t\tconst lastIteration = result.iterations[result.iterations.length - 1]\n\t\t\tif (lastIteration && lastIteration.controllerResult.piInvocation.exitCode !== 0) {\n\t\t\t\tprocess.exitCode = lastIteration.controllerResult.piInvocation.exitCode\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\tcase \"attach\":\n\t\t\tattachTownAgent(args)\n\t\t\tbreak\n\t\tcase \"board\":\n\t\t\tshowTownBoard(args)\n\t\t\tbreak\n\t\tcase \"continue\":\n\t\t\tcontinueTownAgent(args)\n\t\t\tbreak\n\t\tcase \"delegate\":\n\t\t\tdelegateTownTask(args)\n\t\t\tbreak\n\t\tcase \"mayor\":\n\t\t\topenTownMayor(args)\n\t\t\tbreak\n\t\tcase \"msg\":\n\t\t\tmessageTownAgent(args)\n\t\t\tbreak\n\t\tcase \"peek\":\n\t\t\tpeekTownAgent(args)\n\t\t\tbreak\n\t\tcase \"spawn\":\n\t\t\tspawnTownAgent(args)\n\t\t\tbreak\n\t\tcase \"status\":\n\t\t\tshowTownStatus(args)\n\t\t\tbreak\n\t\tcase \"watch\":\n\t\t\twatchTown(args)\n\t\t\tbreak\n\t\tcase \"doctor\": {\n\t\t\tconst result = runDoctor()\n\t\t\tif (!result.ok) process.exitCode = 1\n\t\t\tbreak\n\t\t}\n\t\tdefault:\n\t\t\tconsole.log(`Unknown command: ${command}`)\n\t\t\tprintHelp()\n\t\t\tprocess.exitCode = 1\n\t\t\tbreak\n\t}\n}\n\nif (isDirectExecution(import.meta.url)) {\n\trunCli()\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region ../core/src/pi.ts
|
|
2
|
+
function detectPiAuthFailure(stderr, stdout) {
|
|
3
|
+
const output = `${stdout}\n${stderr}`.toLowerCase();
|
|
4
|
+
return output.includes("no models available") || output.includes("not authenticated") || output.includes("authentication") || output.includes("/login") || output.includes("api key");
|
|
5
|
+
}
|
|
6
|
+
function createPiAuthHelpMessage() {
|
|
7
|
+
return "Pi appears to be installed but not authenticated or configured. Verify Pi works first: pi -p \"hello\". Either set an API key or run `pi` and use `/login`.";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { detectPiAuthFailure as n, createPiAuthHelpMessage as t };
|
|
12
|
+
//# sourceMappingURL=pi-C0fURZj7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-C0fURZj7.mjs","names":[],"sources":["../../core/src/pi.ts"],"sourcesContent":["export function detectPiAuthFailure(stderr: string, stdout: string): boolean {\n\tconst output = `${stdout}\\n${stderr}`.toLowerCase()\n\treturn (\n\t\toutput.includes(\"no models available\") ||\n\t\toutput.includes(\"not authenticated\") ||\n\t\toutput.includes(\"authentication\") ||\n\t\toutput.includes(\"/login\") ||\n\t\toutput.includes(\"api key\")\n\t)\n}\n\nexport function createPiAuthHelpMessage(): string {\n\treturn 'Pi appears to be installed but not authenticated or configured. Verify Pi works first: pi -p \"hello\". Either set an API key or run `pi` and use `/login`.'\n}\n"],"mappings":";AAAA,SAAgB,oBAAoB,QAAgB,QAAyB;CAC5E,MAAM,SAAS,GAAG,OAAO,IAAI,SAAS,aAAa;AACnD,QACC,OAAO,SAAS,sBAAsB,IACtC,OAAO,SAAS,oBAAoB,IACpC,OAAO,SAAS,iBAAiB,IACjC,OAAO,SAAS,SAAS,IACzB,OAAO,SAAS,UAAU;;AAI5B,SAAgB,0BAAkC;AACjD,QAAO"}
|
package/dist/run.d.mts
CHANGED
package/dist/run.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { t as runController } from "./controller-9ihAZj3V.mjs";
|
|
2
|
+
import { t as isDirectExecution } from "./entrypoint-CyJDLudQ.mjs";
|
|
3
|
+
import { a as getRecommendedPlanDir, c as getRepoLatestRunPointerPath, d as createRepoSlug, i as getLatestRunPointerPath, l as getTownHomeDir, m as getRepoRoot, p as getRepoIdentity, r as resolveRunConfig, s as getRepoArtifactsDir } from "./config-CUpe9o0x.mjs";
|
|
3
4
|
import { existsSync, mkdirSync, statSync, writeFileSync } from "node:fs";
|
|
4
5
|
import { dirname, join } from "node:path";
|
|
6
|
+
import { readPiTownMayorPrompt, resolvePiTownExtensionPath } from "@schilderlabs/pitown-package";
|
|
5
7
|
|
|
6
8
|
//#region src/run.ts
|
|
7
9
|
function writeJson(path, value) {
|
|
@@ -39,7 +41,9 @@ function runTown(argv = process.argv.slice(2)) {
|
|
|
39
41
|
goal: config.goal,
|
|
40
42
|
mode: "single-pi",
|
|
41
43
|
planPath: config.plan,
|
|
42
|
-
recommendedPlanDir
|
|
44
|
+
recommendedPlanDir,
|
|
45
|
+
appendedSystemPrompt: readPiTownMayorPrompt(),
|
|
46
|
+
extensionPath: resolvePiTownExtensionPath()
|
|
43
47
|
});
|
|
44
48
|
const latestPointer = createLatestRunPointer(result, repoSlug, repoRoot);
|
|
45
49
|
writeJson(getLatestRunPointerPath(), latestPointer);
|
|
@@ -51,6 +55,7 @@ function runTown(argv = process.argv.slice(2)) {
|
|
|
51
55
|
console.log(`- artifacts: ${result.runDir}`);
|
|
52
56
|
console.log(`- latest metrics: ${latestPointer.metricsPath}`);
|
|
53
57
|
console.log(`- pi exit code: ${result.piInvocation.exitCode}`);
|
|
58
|
+
if (!result.summary.success) console.log(`- note: ${result.summary.message}`);
|
|
54
59
|
if (result.manifest.planPath) console.log(`- plan path: ${result.manifest.planPath}`);
|
|
55
60
|
if (result.summary.recommendedPlanDir) console.log(`- recommended plans: ${result.summary.recommendedPlanDir}`);
|
|
56
61
|
return result;
|
package/dist/run.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.mjs","names":[],"sources":["../src/run.ts"],"sourcesContent":["import { existsSync, mkdirSync, statSync, writeFileSync } from \"node:fs\"\nimport { dirname, join } from \"node:path\"\nimport {\n\tcreateRepoSlug,\n\tgetRepoIdentity,\n\tgetRepoRoot,\n\trunController,\n\ttype ControllerRunResult,\n} from \"../../core/src/index.js\"\nimport { isDirectExecution } from \"./entrypoint.js\"\nimport { resolveRunConfig } from \"./config.js\"\nimport {\n\tgetLatestRunPointerPath,\n\tgetRecommendedPlanDir,\n\tgetRepoArtifactsDir,\n\tgetRepoLatestRunPointerPath,\n\tgetTownHomeDir,\n} from \"./paths.js\"\n\ninterface LatestRunPointer {\n\trepoSlug: string\n\trepoRoot: string\n\trunId: string\n\trunDir: string\n\tlatestDir: string\n\tmanifestPath: string\n\tmetricsPath: string\n\tsummaryPath: string\n\tupdatedAt: string\n}\n\nfunction writeJson(path: string, value: unknown) {\n\tmkdirSync(dirname(path), { recursive: true })\n\twriteFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\")\n}\n\nfunction assertDirectory(path: string, label: string) {\n\tif (!existsSync(path)) throw new Error(`${label} does not exist: ${path}`)\n\tif (!statSync(path).isDirectory()) throw new Error(`${label} is not a directory: ${path}`)\n}\n\nfunction createLatestRunPointer(result: ControllerRunResult, repoSlug: string, repoRoot: string): LatestRunPointer {\n\treturn {\n\t\trepoSlug,\n\t\trepoRoot,\n\t\trunId: result.runId,\n\t\trunDir: result.runDir,\n\t\tlatestDir: result.latestDir,\n\t\tmanifestPath: join(result.latestDir, \"manifest.json\"),\n\t\tmetricsPath: join(result.latestDir, \"metrics.json\"),\n\t\tsummaryPath: join(result.latestDir, \"run-summary.json\"),\n\t\tupdatedAt: new Date().toISOString(),\n\t}\n}\n\nexport function runTown(argv = process.argv.slice(2)): ControllerRunResult {\n\tconst config = resolveRunConfig(argv)\n\tassertDirectory(config.repo, \"Target repo\")\n\tif (config.plan) assertDirectory(config.plan, \"Plan path\")\n\n\tconst townHome = getTownHomeDir()\n\tmkdirSync(townHome, { recursive: true })\n\n\tconst repoRoot = getRepoRoot(config.repo)\n\tconst repoId = getRepoIdentity(repoRoot)\n\tconst repoSlug = createRepoSlug(repoId, repoRoot)\n\tconst recommendedPlanDir = config.plan ? null : getRecommendedPlanDir(repoSlug)\n\tconst artifactsDir = getRepoArtifactsDir(repoSlug)\n\n\tconst result = runController({\n\t\tartifactsDir,\n\t\tcwd: repoRoot,\n\t\tgoal: config.goal,\n\t\tmode: \"single-pi\",\n\t\tplanPath: config.plan,\n\t\trecommendedPlanDir,\n\t})\n\n\tconst latestPointer = createLatestRunPointer(result, repoSlug, repoRoot)\n\twriteJson(getLatestRunPointerPath(), latestPointer)\n\twriteJson(getRepoLatestRunPointerPath(repoSlug), latestPointer)\n\n\tconsole.log(\"[pitown] run written\")\n\tconsole.log(`- run id: ${result.runId}`)\n\tconsole.log(`- repo root: ${result.manifest.repoRoot}`)\n\tconsole.log(`- branch: ${result.manifest.branch}`)\n\tconsole.log(`- artifacts: ${result.runDir}`)\n\tconsole.log(`- latest metrics: ${latestPointer.metricsPath}`)\n\tconsole.log(`- pi exit code: ${result.piInvocation.exitCode}`)\n\tif (result.manifest.planPath) console.log(`- plan path: ${result.manifest.planPath}`)\n\tif (result.summary.recommendedPlanDir) console.log(`- recommended plans: ${result.summary.recommendedPlanDir}`)\n\n\treturn result\n}\n\nif (isDirectExecution(import.meta.url)) {\n\tconst result = runTown()\n\tif (result.piInvocation.exitCode !== 0) process.exitCode = result.piInvocation.exitCode\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.mjs","names":[],"sources":["../src/run.ts"],"sourcesContent":["import { existsSync, mkdirSync, statSync, writeFileSync } from \"node:fs\"\nimport { dirname, join } from \"node:path\"\nimport { readPiTownMayorPrompt, resolvePiTownExtensionPath } from \"@schilderlabs/pitown-package\"\nimport {\n\tcreateRepoSlug,\n\tgetRepoIdentity,\n\tgetRepoRoot,\n\trunController,\n\ttype ControllerRunResult,\n} from \"../../core/src/index.js\"\nimport { isDirectExecution } from \"./entrypoint.js\"\nimport { resolveRunConfig } from \"./config.js\"\nimport {\n\tgetLatestRunPointerPath,\n\tgetRecommendedPlanDir,\n\tgetRepoArtifactsDir,\n\tgetRepoLatestRunPointerPath,\n\tgetTownHomeDir,\n} from \"./paths.js\"\n\ninterface LatestRunPointer {\n\trepoSlug: string\n\trepoRoot: string\n\trunId: string\n\trunDir: string\n\tlatestDir: string\n\tmanifestPath: string\n\tmetricsPath: string\n\tsummaryPath: string\n\tupdatedAt: string\n}\n\nfunction writeJson(path: string, value: unknown) {\n\tmkdirSync(dirname(path), { recursive: true })\n\twriteFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\")\n}\n\nfunction assertDirectory(path: string, label: string) {\n\tif (!existsSync(path)) throw new Error(`${label} does not exist: ${path}`)\n\tif (!statSync(path).isDirectory()) throw new Error(`${label} is not a directory: ${path}`)\n}\n\nfunction createLatestRunPointer(result: ControllerRunResult, repoSlug: string, repoRoot: string): LatestRunPointer {\n\treturn {\n\t\trepoSlug,\n\t\trepoRoot,\n\t\trunId: result.runId,\n\t\trunDir: result.runDir,\n\t\tlatestDir: result.latestDir,\n\t\tmanifestPath: join(result.latestDir, \"manifest.json\"),\n\t\tmetricsPath: join(result.latestDir, \"metrics.json\"),\n\t\tsummaryPath: join(result.latestDir, \"run-summary.json\"),\n\t\tupdatedAt: new Date().toISOString(),\n\t}\n}\n\nexport function runTown(argv = process.argv.slice(2)): ControllerRunResult {\n\tconst config = resolveRunConfig(argv)\n\tassertDirectory(config.repo, \"Target repo\")\n\tif (config.plan) assertDirectory(config.plan, \"Plan path\")\n\n\tconst townHome = getTownHomeDir()\n\tmkdirSync(townHome, { recursive: true })\n\n\tconst repoRoot = getRepoRoot(config.repo)\n\tconst repoId = getRepoIdentity(repoRoot)\n\tconst repoSlug = createRepoSlug(repoId, repoRoot)\n\tconst recommendedPlanDir = config.plan ? null : getRecommendedPlanDir(repoSlug)\n\tconst artifactsDir = getRepoArtifactsDir(repoSlug)\n\n\tconst result = runController({\n\t\tartifactsDir,\n\t\tcwd: repoRoot,\n\t\tgoal: config.goal,\n\t\tmode: \"single-pi\",\n\t\tplanPath: config.plan,\n\t\trecommendedPlanDir,\n\t\tappendedSystemPrompt: readPiTownMayorPrompt(),\n\t\textensionPath: resolvePiTownExtensionPath(),\n\t})\n\n\tconst latestPointer = createLatestRunPointer(result, repoSlug, repoRoot)\n\twriteJson(getLatestRunPointerPath(), latestPointer)\n\twriteJson(getRepoLatestRunPointerPath(repoSlug), latestPointer)\n\n\tconsole.log(\"[pitown] run written\")\n\tconsole.log(`- run id: ${result.runId}`)\n\tconsole.log(`- repo root: ${result.manifest.repoRoot}`)\n\tconsole.log(`- branch: ${result.manifest.branch}`)\n\tconsole.log(`- artifacts: ${result.runDir}`)\n\tconsole.log(`- latest metrics: ${latestPointer.metricsPath}`)\n\tconsole.log(`- pi exit code: ${result.piInvocation.exitCode}`)\n\tif (!result.summary.success) console.log(`- note: ${result.summary.message}`)\n\tif (result.manifest.planPath) console.log(`- plan path: ${result.manifest.planPath}`)\n\tif (result.summary.recommendedPlanDir) console.log(`- recommended plans: ${result.summary.recommendedPlanDir}`)\n\n\treturn result\n}\n\nif (isDirectExecution(import.meta.url)) {\n\tconst result = runTown()\n\tif (result.piInvocation.exitCode !== 0) process.exitCode = result.piInvocation.exitCode\n}\n"],"mappings":";;;;;;;;AAgCA,SAAS,UAAU,MAAc,OAAgB;AAChD,WAAU,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AAC7C,eAAc,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC,KAAK,QAAQ;;AAGpE,SAAS,gBAAgB,MAAc,OAAe;AACrD,KAAI,CAAC,WAAW,KAAK,CAAE,OAAM,IAAI,MAAM,GAAG,MAAM,mBAAmB,OAAO;AAC1E,KAAI,CAAC,SAAS,KAAK,CAAC,aAAa,CAAE,OAAM,IAAI,MAAM,GAAG,MAAM,uBAAuB,OAAO;;AAG3F,SAAS,uBAAuB,QAA6B,UAAkB,UAAoC;AAClH,QAAO;EACN;EACA;EACA,OAAO,OAAO;EACd,QAAQ,OAAO;EACf,WAAW,OAAO;EAClB,cAAc,KAAK,OAAO,WAAW,gBAAgB;EACrD,aAAa,KAAK,OAAO,WAAW,eAAe;EACnD,aAAa,KAAK,OAAO,WAAW,mBAAmB;EACvD,4BAAW,IAAI,MAAM,EAAC,aAAa;EACnC;;AAGF,SAAgB,QAAQ,OAAO,QAAQ,KAAK,MAAM,EAAE,EAAuB;CAC1E,MAAM,SAAS,iBAAiB,KAAK;AACrC,iBAAgB,OAAO,MAAM,cAAc;AAC3C,KAAI,OAAO,KAAM,iBAAgB,OAAO,MAAM,YAAY;AAG1D,WADiB,gBAAgB,EACb,EAAE,WAAW,MAAM,CAAC;CAExC,MAAM,WAAW,YAAY,OAAO,KAAK;CAEzC,MAAM,WAAW,eADF,gBAAgB,SAAS,EACA,SAAS;CACjD,MAAM,qBAAqB,OAAO,OAAO,OAAO,sBAAsB,SAAS;CAG/E,MAAM,SAAS,cAAc;EAC5B,cAHoB,oBAAoB,SAAS;EAIjD,KAAK;EACL,MAAM,OAAO;EACb,MAAM;EACN,UAAU,OAAO;EACjB;EACA,sBAAsB,uBAAuB;EAC7C,eAAe,4BAA4B;EAC3C,CAAC;CAEF,MAAM,gBAAgB,uBAAuB,QAAQ,UAAU,SAAS;AACxE,WAAU,yBAAyB,EAAE,cAAc;AACnD,WAAU,4BAA4B,SAAS,EAAE,cAAc;AAE/D,SAAQ,IAAI,uBAAuB;AACnC,SAAQ,IAAI,aAAa,OAAO,QAAQ;AACxC,SAAQ,IAAI,gBAAgB,OAAO,SAAS,WAAW;AACvD,SAAQ,IAAI,aAAa,OAAO,SAAS,SAAS;AAClD,SAAQ,IAAI,gBAAgB,OAAO,SAAS;AAC5C,SAAQ,IAAI,qBAAqB,cAAc,cAAc;AAC7D,SAAQ,IAAI,mBAAmB,OAAO,aAAa,WAAW;AAC9D,KAAI,CAAC,OAAO,QAAQ,QAAS,SAAQ,IAAI,WAAW,OAAO,QAAQ,UAAU;AAC7E,KAAI,OAAO,SAAS,SAAU,SAAQ,IAAI,gBAAgB,OAAO,SAAS,WAAW;AACrF,KAAI,OAAO,QAAQ,mBAAoB,SAAQ,IAAI,wBAAwB,OAAO,QAAQ,qBAAqB;AAE/G,QAAO;;AAGR,IAAI,kBAAkB,OAAO,KAAK,IAAI,EAAE;CACvC,MAAM,SAAS,SAAS;AACxB,KAAI,OAAO,aAAa,aAAa,EAAG,SAAQ,WAAW,OAAO,aAAa"}
|
package/dist/status.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as isDirectExecution } from "./entrypoint-CyJDLudQ.mjs";
|
|
2
|
+
import { c as getRepoLatestRunPointerPath, d as createRepoSlug, i as getLatestRunPointerPath, l as getTownHomeDir, m as getRepoRoot, p as getRepoIdentity, s as getRepoArtifactsDir, t as parseCliFlags } from "./config-CUpe9o0x.mjs";
|
|
2
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
|
package/dist/status.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.mjs","names":[],"sources":["../src/status.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { createRepoSlug, getRepoIdentity, getRepoRoot } from \"../../core/src/index.js\"\nimport { parseCliFlags } from \"./config.js\"\nimport { isDirectExecution } from \"./entrypoint.js\"\nimport {\n\tgetLatestRunPointerPath,\n\tgetRepoArtifactsDir,\n\tgetRepoLatestRunPointerPath,\n\tgetTownHomeDir,\n} from \"./paths.js\"\n\ninterface LatestRunPointer {\n\trepoSlug: string\n\trepoRoot: string\n\trunId?: string\n\trunDir?: string\n\tlatestDir: string\n\tmanifestPath: string\n\tmetricsPath: string\n\tsummaryPath: string\n\tupdatedAt?: string\n}\n\nfunction readJson<T>(path: string): T {\n\treturn JSON.parse(readFileSync(path, \"utf-8\")) as T\n}\n\nfunction createFallbackPointer(repoRoot: string, repoSlug: string): LatestRunPointer {\n\tconst latestDir = join(getRepoArtifactsDir(repoSlug), \"latest\")\n\treturn {\n\t\trepoSlug,\n\t\trepoRoot,\n\t\tlatestDir,\n\t\tmanifestPath: join(latestDir, \"manifest.json\"),\n\t\tmetricsPath: join(latestDir, \"metrics.json\"),\n\t\tsummaryPath: join(latestDir, \"run-summary.json\"),\n\t}\n}\n\nexport function resolveLatestRunPointer(argv = process.argv.slice(2)): LatestRunPointer | null {\n\tconst flags = parseCliFlags(argv)\n\n\tif (flags.repo) {\n\t\tconst repoRoot = getRepoRoot(flags.repo)\n\t\tconst repoSlug = createRepoSlug(getRepoIdentity(repoRoot), repoRoot)\n\t\tconst repoPointerPath = getRepoLatestRunPointerPath(repoSlug)\n\t\tif (existsSync(repoPointerPath)) return readJson<LatestRunPointer>(repoPointerPath)\n\t\treturn createFallbackPointer(repoRoot, repoSlug)\n\t}\n\n\tconst latestPointerPath = getLatestRunPointerPath()\n\tif (!existsSync(latestPointerPath)) return null\n\treturn readJson<LatestRunPointer>(latestPointerPath)\n}\n\nexport function showTownStatus(argv = process.argv.slice(2)) {\n\tconst latest = resolveLatestRunPointer(argv)\n\tconsole.log(\"[pitown] status\")\n\tconsole.log(`- town home: ${getTownHomeDir()}`)\n\n\tif (latest === null) {\n\t\tconsole.log(\"- no local runs found yet\")\n\t\tconsole.log(`- expected pointer: ${getLatestRunPointerPath()}`)\n\t\treturn\n\t}\n\n\tif (existsSync(latest.summaryPath)) {\n\t\tconst summary = readJson<{\n\t\t\trunId?: string\n\t\t\tmode?: string\n\t\t\tmessage?: string\n\t\t\tpiExitCode?: number\n\t\t}>(latest.summaryPath)\n\t\tif (summary.runId) console.log(`- latest run: ${summary.runId}`)\n\t\tif (summary.mode) console.log(`- mode: ${summary.mode}`)\n\t\tif (summary.piExitCode !== undefined) console.log(`- pi exit code: ${summary.piExitCode}`)\n\t\tif (summary.message) console.log(`- note: ${summary.message}`)\n\t}\n\n\tif (existsSync(latest.manifestPath)) {\n\t\tconst manifest = readJson<{\n\t\t\trepoRoot?: string\n\t\t\tbranch?: string\n\t\t\tgoal?: string | null\n\t\t\tplanPath?: string | null\n\t\t\trecommendedPlanDir?: string | null\n\t\t\tstopReason?: string | null\n\t\t}>(latest.manifestPath)\n\t\tif (manifest.repoRoot) console.log(`- repo root: ${manifest.repoRoot}`)\n\t\tif (manifest.branch) console.log(`- branch: ${manifest.branch}`)\n\t\tif (manifest.goal) console.log(`- goal: ${manifest.goal}`)\n\t\tif (manifest.planPath) console.log(`- plan path: ${manifest.planPath}`)\n\t\tif (!manifest.planPath && manifest.recommendedPlanDir) {\n\t\t\tconsole.log(`- recommended plans: ${manifest.recommendedPlanDir}`)\n\t\t}\n\t\tif (manifest.stopReason) console.log(`- stop reason: ${manifest.stopReason}`)\n\t}\n\n\tif (!existsSync(latest.metricsPath)) {\n\t\tconsole.log(\"- no metrics snapshot found yet\")\n\t\tconsole.log(`- expected path: ${latest.metricsPath}`)\n\t\treturn\n\t}\n\n\tconsole.log(`- metrics file: ${latest.metricsPath}`)\n\tconsole.log(readFileSync(latest.metricsPath, \"utf-8\").trim())\n}\n\nif (isDirectExecution(import.meta.url)) {\n\tshowTownStatus()\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.mjs","names":[],"sources":["../src/status.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { createRepoSlug, getRepoIdentity, getRepoRoot } from \"../../core/src/index.js\"\nimport { parseCliFlags } from \"./config.js\"\nimport { isDirectExecution } from \"./entrypoint.js\"\nimport {\n\tgetLatestRunPointerPath,\n\tgetRepoArtifactsDir,\n\tgetRepoLatestRunPointerPath,\n\tgetTownHomeDir,\n} from \"./paths.js\"\n\ninterface LatestRunPointer {\n\trepoSlug: string\n\trepoRoot: string\n\trunId?: string\n\trunDir?: string\n\tlatestDir: string\n\tmanifestPath: string\n\tmetricsPath: string\n\tsummaryPath: string\n\tupdatedAt?: string\n}\n\nfunction readJson<T>(path: string): T {\n\treturn JSON.parse(readFileSync(path, \"utf-8\")) as T\n}\n\nfunction createFallbackPointer(repoRoot: string, repoSlug: string): LatestRunPointer {\n\tconst latestDir = join(getRepoArtifactsDir(repoSlug), \"latest\")\n\treturn {\n\t\trepoSlug,\n\t\trepoRoot,\n\t\tlatestDir,\n\t\tmanifestPath: join(latestDir, \"manifest.json\"),\n\t\tmetricsPath: join(latestDir, \"metrics.json\"),\n\t\tsummaryPath: join(latestDir, \"run-summary.json\"),\n\t}\n}\n\nexport function resolveLatestRunPointer(argv = process.argv.slice(2)): LatestRunPointer | null {\n\tconst flags = parseCliFlags(argv)\n\n\tif (flags.repo) {\n\t\tconst repoRoot = getRepoRoot(flags.repo)\n\t\tconst repoSlug = createRepoSlug(getRepoIdentity(repoRoot), repoRoot)\n\t\tconst repoPointerPath = getRepoLatestRunPointerPath(repoSlug)\n\t\tif (existsSync(repoPointerPath)) return readJson<LatestRunPointer>(repoPointerPath)\n\t\treturn createFallbackPointer(repoRoot, repoSlug)\n\t}\n\n\tconst latestPointerPath = getLatestRunPointerPath()\n\tif (!existsSync(latestPointerPath)) return null\n\treturn readJson<LatestRunPointer>(latestPointerPath)\n}\n\nexport function showTownStatus(argv = process.argv.slice(2)) {\n\tconst latest = resolveLatestRunPointer(argv)\n\tconsole.log(\"[pitown] status\")\n\tconsole.log(`- town home: ${getTownHomeDir()}`)\n\n\tif (latest === null) {\n\t\tconsole.log(\"- no local runs found yet\")\n\t\tconsole.log(`- expected pointer: ${getLatestRunPointerPath()}`)\n\t\treturn\n\t}\n\n\tif (existsSync(latest.summaryPath)) {\n\t\tconst summary = readJson<{\n\t\t\trunId?: string\n\t\t\tmode?: string\n\t\t\tmessage?: string\n\t\t\tpiExitCode?: number\n\t\t}>(latest.summaryPath)\n\t\tif (summary.runId) console.log(`- latest run: ${summary.runId}`)\n\t\tif (summary.mode) console.log(`- mode: ${summary.mode}`)\n\t\tif (summary.piExitCode !== undefined) console.log(`- pi exit code: ${summary.piExitCode}`)\n\t\tif (summary.message) console.log(`- note: ${summary.message}`)\n\t}\n\n\tif (existsSync(latest.manifestPath)) {\n\t\tconst manifest = readJson<{\n\t\t\trepoRoot?: string\n\t\t\tbranch?: string\n\t\t\tgoal?: string | null\n\t\t\tplanPath?: string | null\n\t\t\trecommendedPlanDir?: string | null\n\t\t\tstopReason?: string | null\n\t\t}>(latest.manifestPath)\n\t\tif (manifest.repoRoot) console.log(`- repo root: ${manifest.repoRoot}`)\n\t\tif (manifest.branch) console.log(`- branch: ${manifest.branch}`)\n\t\tif (manifest.goal) console.log(`- goal: ${manifest.goal}`)\n\t\tif (manifest.planPath) console.log(`- plan path: ${manifest.planPath}`)\n\t\tif (!manifest.planPath && manifest.recommendedPlanDir) {\n\t\t\tconsole.log(`- recommended plans: ${manifest.recommendedPlanDir}`)\n\t\t}\n\t\tif (manifest.stopReason) console.log(`- stop reason: ${manifest.stopReason}`)\n\t}\n\n\tif (!existsSync(latest.metricsPath)) {\n\t\tconsole.log(\"- no metrics snapshot found yet\")\n\t\tconsole.log(`- expected path: ${latest.metricsPath}`)\n\t\treturn\n\t}\n\n\tconsole.log(`- metrics file: ${latest.metricsPath}`)\n\tconsole.log(readFileSync(latest.metricsPath, \"utf-8\").trim())\n}\n\nif (isDirectExecution(import.meta.url)) {\n\tshowTownStatus()\n}\n"],"mappings":";;;;;;AAwBA,SAAS,SAAY,MAAiB;AACrC,QAAO,KAAK,MAAM,aAAa,MAAM,QAAQ,CAAC;;AAG/C,SAAS,sBAAsB,UAAkB,UAAoC;CACpF,MAAM,YAAY,KAAK,oBAAoB,SAAS,EAAE,SAAS;AAC/D,QAAO;EACN;EACA;EACA;EACA,cAAc,KAAK,WAAW,gBAAgB;EAC9C,aAAa,KAAK,WAAW,eAAe;EAC5C,aAAa,KAAK,WAAW,mBAAmB;EAChD;;AAGF,SAAgB,wBAAwB,OAAO,QAAQ,KAAK,MAAM,EAAE,EAA2B;CAC9F,MAAM,QAAQ,cAAc,KAAK;AAEjC,KAAI,MAAM,MAAM;EACf,MAAM,WAAW,YAAY,MAAM,KAAK;EACxC,MAAM,WAAW,eAAe,gBAAgB,SAAS,EAAE,SAAS;EACpE,MAAM,kBAAkB,4BAA4B,SAAS;AAC7D,MAAI,WAAW,gBAAgB,CAAE,QAAO,SAA2B,gBAAgB;AACnF,SAAO,sBAAsB,UAAU,SAAS;;CAGjD,MAAM,oBAAoB,yBAAyB;AACnD,KAAI,CAAC,WAAW,kBAAkB,CAAE,QAAO;AAC3C,QAAO,SAA2B,kBAAkB;;AAGrD,SAAgB,eAAe,OAAO,QAAQ,KAAK,MAAM,EAAE,EAAE;CAC5D,MAAM,SAAS,wBAAwB,KAAK;AAC5C,SAAQ,IAAI,kBAAkB;AAC9B,SAAQ,IAAI,gBAAgB,gBAAgB,GAAG;AAE/C,KAAI,WAAW,MAAM;AACpB,UAAQ,IAAI,4BAA4B;AACxC,UAAQ,IAAI,uBAAuB,yBAAyB,GAAG;AAC/D;;AAGD,KAAI,WAAW,OAAO,YAAY,EAAE;EACnC,MAAM,UAAU,SAKb,OAAO,YAAY;AACtB,MAAI,QAAQ,MAAO,SAAQ,IAAI,iBAAiB,QAAQ,QAAQ;AAChE,MAAI,QAAQ,KAAM,SAAQ,IAAI,WAAW,QAAQ,OAAO;AACxD,MAAI,QAAQ,eAAe,OAAW,SAAQ,IAAI,mBAAmB,QAAQ,aAAa;AAC1F,MAAI,QAAQ,QAAS,SAAQ,IAAI,WAAW,QAAQ,UAAU;;AAG/D,KAAI,WAAW,OAAO,aAAa,EAAE;EACpC,MAAM,WAAW,SAOd,OAAO,aAAa;AACvB,MAAI,SAAS,SAAU,SAAQ,IAAI,gBAAgB,SAAS,WAAW;AACvE,MAAI,SAAS,OAAQ,SAAQ,IAAI,aAAa,SAAS,SAAS;AAChE,MAAI,SAAS,KAAM,SAAQ,IAAI,WAAW,SAAS,OAAO;AAC1D,MAAI,SAAS,SAAU,SAAQ,IAAI,gBAAgB,SAAS,WAAW;AACvE,MAAI,CAAC,SAAS,YAAY,SAAS,mBAClC,SAAQ,IAAI,wBAAwB,SAAS,qBAAqB;AAEnE,MAAI,SAAS,WAAY,SAAQ,IAAI,kBAAkB,SAAS,aAAa;;AAG9E,KAAI,CAAC,WAAW,OAAO,YAAY,EAAE;AACpC,UAAQ,IAAI,kCAAkC;AAC9C,UAAQ,IAAI,oBAAoB,OAAO,cAAc;AACrD;;AAGD,SAAQ,IAAI,mBAAmB,OAAO,cAAc;AACpD,SAAQ,IAAI,aAAa,OAAO,aAAa,QAAQ,CAAC,MAAM,CAAC;;AAG9D,IAAI,kBAAkB,OAAO,KAAK,IAAI,CACrC,iBAAgB"}
|
package/dist/watch.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as isDirectExecution } from "./entrypoint-CyJDLudQ.mjs";
|
|
2
|
+
import { l as getTownHomeDir } from "./config-CUpe9o0x.mjs";
|
|
2
3
|
import { resolveLatestRunPointer, showTownStatus } from "./status.mjs";
|
|
3
4
|
import { existsSync, watchFile } from "node:fs";
|
|
4
5
|
|
package/dist/watch.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.mjs","names":[],"sources":["../src/watch.ts"],"sourcesContent":["import { existsSync, watchFile } from \"node:fs\"\nimport { isDirectExecution } from \"./entrypoint.js\"\nimport { getTownHomeDir } from \"./paths.js\"\nimport { resolveLatestRunPointer, showTownStatus } from \"./status.js\"\n\nexport function watchTown(argv = process.argv.slice(2)) {\n\tconst latest = resolveLatestRunPointer(argv)\n\tconst metricsPath = latest?.metricsPath\n\n\tconsole.log(\"[pitown] watch\")\n\tconsole.log(`- town home: ${getTownHomeDir()}`)\n\tconsole.log(\"- press Ctrl+C to stop\")\n\tshowTownStatus(argv)\n\n\tif (!metricsPath || !existsSync(metricsPath)) {\n\t\tconsole.log(\"- metrics file does not exist yet; watch will activate after the first run\")\n\t\treturn\n\t}\n\n\twatchFile(metricsPath, { interval: 1000 }, () => {\n\t\tconsole.log(\"\\n[pitown] metrics updated\")\n\t\tshowTownStatus(argv)\n\t})\n}\n\nif (isDirectExecution(import.meta.url)) {\n\twatchTown()\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"watch.mjs","names":[],"sources":["../src/watch.ts"],"sourcesContent":["import { existsSync, watchFile } from \"node:fs\"\nimport { isDirectExecution } from \"./entrypoint.js\"\nimport { getTownHomeDir } from \"./paths.js\"\nimport { resolveLatestRunPointer, showTownStatus } from \"./status.js\"\n\nexport function watchTown(argv = process.argv.slice(2)) {\n\tconst latest = resolveLatestRunPointer(argv)\n\tconst metricsPath = latest?.metricsPath\n\n\tconsole.log(\"[pitown] watch\")\n\tconsole.log(`- town home: ${getTownHomeDir()}`)\n\tconsole.log(\"- press Ctrl+C to stop\")\n\tshowTownStatus(argv)\n\n\tif (!metricsPath || !existsSync(metricsPath)) {\n\t\tconsole.log(\"- metrics file does not exist yet; watch will activate after the first run\")\n\t\treturn\n\t}\n\n\twatchFile(metricsPath, { interval: 1000 }, () => {\n\t\tconsole.log(\"\\n[pitown] metrics updated\")\n\t\tshowTownStatus(argv)\n\t})\n}\n\nif (isDirectExecution(import.meta.url)) {\n\twatchTown()\n}\n"],"mappings":";;;;;;AAKA,SAAgB,UAAU,OAAO,QAAQ,KAAK,MAAM,EAAE,EAAE;CAEvD,MAAM,cADS,wBAAwB,KAAK,EAChB;AAE5B,SAAQ,IAAI,iBAAiB;AAC7B,SAAQ,IAAI,gBAAgB,gBAAgB,GAAG;AAC/C,SAAQ,IAAI,yBAAyB;AACrC,gBAAe,KAAK;AAEpB,KAAI,CAAC,eAAe,CAAC,WAAW,YAAY,EAAE;AAC7C,UAAQ,IAAI,6EAA6E;AACzF;;AAGD,WAAU,aAAa,EAAE,UAAU,KAAM,QAAQ;AAChD,UAAQ,IAAI,6BAA6B;AACzC,iBAAe,KAAK;GACnB;;AAGH,IAAI,kBAAkB,OAAO,KAAK,IAAI,CACrC,YAAW"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schilderlabs/pitown",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Globally installable CLI for Pi Town",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"node": ">=24"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@schilderlabs/pitown-core": "0.
|
|
24
|
+
"@schilderlabs/pitown-core": "0.2.1",
|
|
25
|
+
"@schilderlabs/pitown-package": "0.2.1"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"eslint": "9.39.3",
|
|
@@ -39,11 +40,11 @@
|
|
|
39
40
|
],
|
|
40
41
|
"repository": {
|
|
41
42
|
"type": "git",
|
|
42
|
-
"url": "git+https://github.com/
|
|
43
|
+
"url": "git+https://github.com/RobSchilderr/pitown.git"
|
|
43
44
|
},
|
|
44
|
-
"homepage": "https://github.com/
|
|
45
|
+
"homepage": "https://github.com/RobSchilderr/pitown#readme",
|
|
45
46
|
"bugs": {
|
|
46
|
-
"url": "https://github.com/
|
|
47
|
+
"url": "https://github.com/RobSchilderr/pitown/issues"
|
|
47
48
|
},
|
|
48
49
|
"publishConfig": {
|
|
49
50
|
"access": "public"
|
|
@@ -53,6 +54,7 @@
|
|
|
53
54
|
"build": "tsdown",
|
|
54
55
|
"lint": "eslint .",
|
|
55
56
|
"test": "vitest run --passWithNoTests",
|
|
57
|
+
"town:doctor": "tsx src/doctor.ts",
|
|
56
58
|
"town:run": "tsx src/run.ts",
|
|
57
59
|
"town:status": "tsx src/status.ts",
|
|
58
60
|
"town:watch": "tsx src/watch.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-Bw-mNdF5.mjs","names":[],"sources":["../src/entrypoint.ts","../../core/src/shell.ts","../../core/src/repo.ts","../src/paths.ts","../src/config.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\"\nimport { resolve } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\nfunction normalizePath(path: string | undefined): string | null {\n\tif (!path) return null\n\ttry {\n\t\treturn realpathSync(path)\n\t} catch {\n\t\treturn resolve(path)\n\t}\n}\n\nexport function isDirectExecution(fileUrl: string, argv1 = process.argv[1]): boolean {\n\tconst modulePath = normalizePath(fileURLToPath(fileUrl))\n\tconst invokedPath = normalizePath(argv1)\n\treturn modulePath !== null && invokedPath !== null && modulePath === invokedPath\n}\n","import { spawnSync } from \"node:child_process\"\n\nexport interface CommandResult {\n\tstdout: string\n\tstderr: string\n\texitCode: number\n}\n\nexport function runCommandSync(\n\tcommand: string,\n\targs: string[],\n\toptions?: { cwd?: string; env?: NodeJS.ProcessEnv },\n): CommandResult {\n\tconst result = spawnSync(command, args, {\n\t\tcwd: options?.cwd,\n\t\tenv: options?.env,\n\t\tencoding: \"utf-8\",\n\t})\n\tconst errorText = result.error instanceof Error ? `${result.error.message}\n` : \"\"\n\n\treturn {\n\t\tstdout: result.stdout ?? \"\",\n\t\tstderr: `${errorText}${result.stderr ?? \"\"}`,\n\t\texitCode: result.status ?? 1,\n\t}\n}\n\nexport function assertCommandAvailable(command: string) {\n\tconst result = spawnSync(command, [\"--help\"], {\n\t\tencoding: \"utf-8\",\n\t\tstdio: \"ignore\",\n\t})\n\n\tif (result.error instanceof Error) {\n\t\tthrow new Error(result.error.message)\n\t}\n}\n\nexport function assertSuccess(result: CommandResult, context: string) {\n\tif (result.exitCode === 0) return\n\tconst details = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join(\"\\n\")\n\tthrow new Error(`${context} failed${details ? `\\n${details}` : \"\"}`)\n}\n","import { createHash } from \"node:crypto\"\nimport { existsSync } from \"node:fs\"\nimport { basename, resolve } from \"node:path\"\nimport { assertSuccess, runCommandSync } from \"./shell.js\"\n\nfunction gitResult(cwd: string, args: string[]) {\n\treturn runCommandSync(\"git\", args, { cwd })\n}\n\nfunction sanitize(value: string): string {\n\treturn value.replace(/[^a-zA-Z0-9._-]+/g, \"-\").replace(/^-+|-+$/g, \"\") || \"repo\"\n}\n\nexport function isGitRepo(cwd: string): boolean {\n\tconst result = gitResult(cwd, [\"rev-parse\", \"--is-inside-work-tree\"])\n\treturn result.exitCode === 0 && result.stdout.trim() === \"true\"\n}\n\nexport function getRepoRoot(cwd: string): string {\n\tif (!isGitRepo(cwd)) return resolve(cwd)\n\tconst result = gitResult(cwd, [\"rev-parse\", \"--show-toplevel\"])\n\tassertSuccess(result, \"git rev-parse --show-toplevel\")\n\treturn resolve(result.stdout.trim())\n}\n\nexport function getCurrentBranch(cwd: string): string | null {\n\tif (!isGitRepo(cwd)) return null\n\tconst result = gitResult(cwd, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n\tif (result.exitCode !== 0) return null\n\tconst branch = result.stdout.trim()\n\treturn branch || null\n}\n\nexport function getRepoIdentity(cwd: string): string {\n\tif (!isGitRepo(cwd)) return resolve(cwd)\n\n\tconst remote = gitResult(cwd, [\"config\", \"--get\", \"remote.origin.url\"])\n\tconst remoteValue = remote.stdout.trim()\n\tif (remote.exitCode === 0 && remoteValue) return remoteValue\n\n\tconst root = gitResult(cwd, [\"rev-parse\", \"--show-toplevel\"])\n\tassertSuccess(root, \"git rev-parse --show-toplevel\")\n\tconst commonDir = gitResult(cwd, [\"rev-parse\", \"--git-common-dir\"])\n\tassertSuccess(commonDir, \"git rev-parse --git-common-dir\")\n\n\tconst rootPath = resolve(root.stdout.trim())\n\tconst commonDirPath = commonDir.stdout.trim()\n\treturn `${basename(rootPath)}:${rootPath}:${existsSync(commonDirPath) ? resolve(commonDirPath) : commonDirPath}`\n}\n\nexport function createRepoSlug(repoId: string, repoRoot: string): string {\n\tconst name = sanitize(basename(repoRoot))\n\tconst digest = createHash(\"sha1\").update(repoId).digest(\"hex\").slice(0, 8)\n\treturn `${name}-${digest}`\n}\n","import { homedir } from \"node:os\"\nimport { join } from \"node:path\"\n\nexport function getTownHomeDir(): string {\n\treturn join(homedir(), \".pi-town\")\n}\n\nexport function getUserConfigPath(): string {\n\treturn join(getTownHomeDir(), \"config.json\")\n}\n\nexport function getPlansRootDir(): string {\n\treturn join(getTownHomeDir(), \"plans\")\n}\n\nexport function getReposRootDir(): string {\n\treturn join(getTownHomeDir(), \"repos\")\n}\n\nexport function getRepoArtifactsDir(repoSlug: string): string {\n\treturn join(getReposRootDir(), repoSlug)\n}\n\nexport function getLatestRunPointerPath(): string {\n\treturn join(getTownHomeDir(), \"latest-run.json\")\n}\n\nexport function getRepoLatestRunPointerPath(repoSlug: string): string {\n\treturn join(getRepoArtifactsDir(repoSlug), \"latest-run.json\")\n}\n\nexport function getRecommendedPlanDir(repoSlug: string): string {\n\treturn join(getPlansRootDir(), repoSlug)\n}\n","import { existsSync, readFileSync } from \"node:fs\"\nimport { dirname, isAbsolute, resolve } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { getUserConfigPath } from \"./paths.js\"\n\nconst DEFAULT_GOAL = \"continue from current scaffold state\"\n\nexport interface CliFlags {\n\trepo?: string\n\tplan?: string\n\tgoal?: string\n\thelp: boolean\n}\n\ninterface UserConfig {\n\trepo?: string\n\tplan?: string\n\tgoal?: string\n}\n\nexport interface ResolvedRunConfig {\n\trepo: string\n\tplan: string | null\n\tgoal: string\n\tconfigPath: string\n}\n\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir()\n\tif (value.startsWith(\"~/\")) return resolve(homedir(), value.slice(2))\n\treturn value\n}\n\nfunction resolvePathValue(value: string | undefined, baseDir: string): string | undefined {\n\tif (!value) return undefined\n\tconst expanded = expandHome(value)\n\treturn isAbsolute(expanded) ? resolve(expanded) : resolve(baseDir, expanded)\n}\n\nexport function parseCliFlags(argv: string[]): CliFlags {\n\tconst flags: CliFlags = { help: false }\n\n\tfor (let index = 0; index < argv.length; index += 1) {\n\t\tconst arg = argv[index]\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tflags.help = true\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--repo=\")) {\n\t\t\tflags.repo = arg.slice(\"--repo=\".length)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg === \"--repo\") {\n\t\t\tconst value = argv[index + 1]\n\t\t\tif (!value) throw new Error(\"Missing value for --repo\")\n\t\t\tflags.repo = value\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--plan=\")) {\n\t\t\tflags.plan = arg.slice(\"--plan=\".length)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg === \"--plan\") {\n\t\t\tconst value = argv[index + 1]\n\t\t\tif (!value) throw new Error(\"Missing value for --plan\")\n\t\t\tflags.plan = value\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg.startsWith(\"--goal=\")) {\n\t\t\tflags.goal = arg.slice(\"--goal=\".length)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg === \"--goal\") {\n\t\t\tconst value = argv[index + 1]\n\t\t\tif (!value) throw new Error(\"Missing value for --goal\")\n\t\t\tflags.goal = value\n\t\t\tindex += 1\n\t\t\tcontinue\n\t\t}\n\n\t\tthrow new Error(`Unknown argument: ${arg}`)\n\t}\n\n\treturn flags\n}\n\nexport function loadUserConfig(): UserConfig {\n\tconst configPath = getUserConfigPath()\n\tif (!existsSync(configPath)) return {}\n\treturn JSON.parse(readFileSync(configPath, \"utf-8\")) as UserConfig\n}\n\nexport function resolveRunConfig(argv: string[]): ResolvedRunConfig {\n\tconst flags = parseCliFlags(argv)\n\tconst configPath = getUserConfigPath()\n\tconst userConfig = loadUserConfig()\n\tconst configDir = dirname(configPath)\n\n\tconst repo =\n\t\tresolvePathValue(flags.repo, process.cwd()) ??\n\t\tresolvePathValue(userConfig.repo, configDir) ??\n\t\tresolve(process.cwd())\n\tconst plan = resolvePathValue(flags.plan, process.cwd()) ?? resolvePathValue(userConfig.plan, configDir) ?? null\n\tconst goal = flags.goal ?? userConfig.goal ?? DEFAULT_GOAL\n\n\treturn {\n\t\trepo,\n\t\tplan,\n\t\tgoal,\n\t\tconfigPath,\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"controller-D7lezZjg.mjs","names":[],"sources":["../../core/src/events.ts","../../core/src/lease.ts","../../core/src/metrics.ts","../../core/src/controller.ts"],"sourcesContent":["import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\"\nimport { dirname } from \"node:path\"\n\nexport function appendJsonl(filePath: string, value: unknown) {\n\tmkdirSync(dirname(filePath), { recursive: true })\n\twriteFileSync(filePath, `${JSON.stringify(value)}\\n`, { encoding: \"utf-8\", flag: \"a\" })\n}\n\nexport function readJsonl<T>(filePath: string): T[] {\n\ttry {\n\t\tconst raw = readFileSync(filePath, \"utf-8\")\n\t\treturn raw\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.map((line) => line.trim())\n\t\t\t.filter(Boolean)\n\t\t\t.map((line) => JSON.parse(line) as T)\n\t} catch {\n\t\treturn []\n\t}\n}\n","import { mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\"\nimport { homedir, hostname } from \"node:os\"\nimport { join } from \"node:path\"\n\ninterface LeaseData {\n\trunId: string\n\trepoId: string\n\tbranch: string\n\tpid: number\n\thostname: string\n\tstartedAt: string\n}\n\nfunction sanitize(value: string): string {\n\treturn value.replace(/[^a-zA-Z0-9._-]+/g, \"_\")\n}\n\nfunction processAlive(pid: number): boolean {\n\tif (!Number.isFinite(pid) || pid <= 0) return false\n\ttry {\n\t\tprocess.kill(pid, 0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function acquireRepoLease(runId: string, repoId: string, branch: string): { path: string; release: () => void } {\n\tconst locksDir = join(homedir(), \".pi-town\", \"locks\")\n\tmkdirSync(locksDir, { recursive: true })\n\n\tconst leasePath = join(locksDir, `pi-town-${sanitize(repoId)}-${sanitize(branch)}.json`)\n\tconst nextData: LeaseData = {\n\t\trunId,\n\t\trepoId,\n\t\tbranch,\n\t\tpid: process.pid,\n\t\thostname: hostname(),\n\t\tstartedAt: new Date().toISOString(),\n\t}\n\n\ttry {\n\t\tconst current = JSON.parse(readFileSync(leasePath, \"utf-8\")) as LeaseData\n\t\tif (processAlive(current.pid)) {\n\t\t\tthrow new Error(`Pi Town lease already held by pid ${current.pid} on ${current.hostname} for run ${current.runId}.`)\n\t\t}\n\t\trmSync(leasePath, { force: true })\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n\t\t\tif (error instanceof Error && error.message.startsWith(\"Pi Town lease already held\")) throw error\n\t\t}\n\t}\n\n\twriteFileSync(leasePath, `${JSON.stringify(nextData, null, 2)}\\n`, \"utf-8\")\n\n\treturn {\n\t\tpath: leasePath,\n\t\trelease: () => {\n\t\t\ttry {\n\t\t\t\tconst current = JSON.parse(readFileSync(leasePath, \"utf-8\")) as LeaseData\n\t\t\t\tif (current.runId === runId) rmSync(leasePath, { force: true })\n\t\t\t} catch {\n\t\t\t\t// ignore cleanup failures\n\t\t\t}\n\t\t},\n\t}\n}\n","import type { FeedbackCycle, InterruptRecord, MetricsSnapshot, TaskAttempt } from \"./types.js\"\n\nfunction round(value: number): number {\n\treturn Math.round(value * 1000) / 1000\n}\n\nfunction diffHours(start: string, end: string): number {\n\treturn (Date.parse(end) - Date.parse(start)) / 3_600_000\n}\n\nfunction average(values: number[]): number | null {\n\tif (values.length === 0) return null\n\treturn values.reduce((sum, value) => sum + value, 0) / values.length\n}\n\nexport function computeInterruptRate(interrupts: InterruptRecord[], taskAttempts: TaskAttempt[]): number {\n\tif (taskAttempts.length === 0) return 0\n\treturn round(interrupts.length / taskAttempts.length)\n}\n\nexport function computeAutonomousCompletionRate(taskAttempts: TaskAttempt[]): number {\n\tconst completed = taskAttempts.filter((task) => task.status === \"completed\")\n\tif (completed.length === 0) return 0\n\tconst autonomous = completed.filter((task) => !task.interrupted)\n\treturn round(autonomous.length / completed.length)\n}\n\nexport function computeContextCoverageScore(interrupts: InterruptRecord[]): number {\n\tconst observed = new Set(interrupts.map((interrupt) => interrupt.category))\n\tif (observed.size === 0) return 0\n\n\tconst covered = new Set(\n\t\tinterrupts.filter((interrupt) => interrupt.fixType).map((interrupt) => interrupt.category),\n\t)\n\n\treturn round(covered.size / observed.size)\n}\n\nexport function computeMeanTimeToCorrect(interrupts: InterruptRecord[]): number | null {\n\tconst resolved = interrupts.filter((interrupt) => interrupt.resolvedAt)\n\tconst hours = resolved.map((interrupt) => diffHours(interrupt.createdAt, interrupt.resolvedAt!))\n\tconst value = average(hours)\n\treturn value === null ? null : round(value)\n}\n\nexport function computeFeedbackToDemoCycleTime(feedbackCycles: FeedbackCycle[]): number | null {\n\tconst hours = feedbackCycles.map((cycle) => diffHours(cycle.feedbackAt, cycle.demoReadyAt))\n\tconst value = average(hours)\n\treturn value === null ? null : round(value)\n}\n\nexport function computeMetrics(input: {\n\ttaskAttempts: TaskAttempt[]\n\tinterrupts: InterruptRecord[]\n\tfeedbackCycles?: FeedbackCycle[]\n}): MetricsSnapshot {\n\tconst observedCategories = new Set(input.interrupts.map((interrupt) => interrupt.category))\n\tconst coveredCategories = new Set(\n\t\tinput.interrupts.filter((interrupt) => interrupt.fixType).map((interrupt) => interrupt.category),\n\t)\n\tconst completedTasks = input.taskAttempts.filter((task) => task.status === \"completed\").length\n\n\treturn {\n\t\tinterruptRate: computeInterruptRate(input.interrupts, input.taskAttempts),\n\t\tautonomousCompletionRate: computeAutonomousCompletionRate(input.taskAttempts),\n\t\tcontextCoverageScore: computeContextCoverageScore(input.interrupts),\n\t\tmeanTimeToCorrectHours: computeMeanTimeToCorrect(input.interrupts),\n\t\tfeedbackToDemoCycleTimeHours: computeFeedbackToDemoCycleTime(input.feedbackCycles ?? []),\n\t\ttotals: {\n\t\t\ttaskAttempts: input.taskAttempts.length,\n\t\t\tcompletedTasks,\n\t\t\tinterrupts: input.interrupts.length,\n\t\t\tobservedInterruptCategories: observedCategories.size,\n\t\t\tcoveredInterruptCategories: coveredCategories.size,\n\t\t},\n\t}\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { appendJsonl } from \"./events.js\"\nimport { acquireRepoLease } from \"./lease.js\"\nimport { computeMetrics } from \"./metrics.js\"\nimport { createRepoSlug, getCurrentBranch, getRepoIdentity, getRepoRoot } from \"./repo.js\"\nimport { assertCommandAvailable, runCommandSync } from \"./shell.js\"\nimport type { ControllerRunResult, PiInvocationRecord, RunManifest, RunOptions, RunSummary } from \"./types.js\"\n\nfunction createRunId(): string {\n\treturn `run-${new Date().toISOString().replace(/[:.]/g, \"-\")}`\n}\n\nfunction writeJson(path: string, value: unknown) {\n\twriteFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\")\n}\n\nfunction writeText(path: string, value: string) {\n\twriteFileSync(path, value, \"utf-8\")\n}\n\nfunction createPiPrompt(input: {\n\trepoRoot: string\n\tplanPath: string | null\n\tgoal: string | null\n\trecommendedPlanDir: string | null\n}): string {\n\tconst goal = input.goal ?? \"continue from current scaffold state\"\n\n\tif (input.planPath) {\n\t\treturn [\n\t\t\t\"Read the private plans in:\",\n\t\t\t`- ${input.planPath}`,\n\t\t\t\"\",\n\t\t\t\"and the current code in:\",\n\t\t\t`- ${input.repoRoot}`,\n\t\t\t\"\",\n\t\t\t`Goal: ${goal}`,\n\t\t\t\"Continue from the current scaffold state.\",\n\t\t\t\"Keep any persisted run artifacts high-signal and avoid copying private plan contents into them.\",\n\t\t].join(\"\\n\")\n\t}\n\n\treturn [\n\t\t`Work in the repository at: ${input.repoRoot}`,\n\t\t`Goal: ${goal}`,\n\t\t\"No private plan path is configured for this run.\",\n\t\tinput.recommendedPlanDir\n\t\t\t? `If you need private plans, use a user-owned location such as: ${input.recommendedPlanDir}`\n\t\t\t: \"If you need private plans, keep them in a user-owned location outside the repo.\",\n\t\t\"Continue from the current scaffold state.\",\n\t].join(\"\\n\")\n}\n\nfunction assertPiRuntimeAvailable(piCommand: string) {\n\ttry {\n\t\tassertCommandAvailable(piCommand)\n\t} catch (error) {\n\t\tif (piCommand === \"pi\") {\n\t\t\tthrow new Error(\n\t\t\t\t[\n\t\t\t\t\t\"Pi Town requires the `pi` CLI to run `pitown run`.\",\n\t\t\t\t\t\"Install Pi: npm install -g @mariozechner/pi-coding-agent\",\n\t\t\t\t\t\"Then authenticate Pi and verify it works: pi -p \\\"hello\\\"\",\n\t\t\t\t\t`Details: ${(error as Error).message}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t)\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t[\n\t\t\t\t`Pi Town could not execute the configured Pi command: ${piCommand}`,\n\t\t\t\t\"Make sure the command exists on PATH or points to an executable file.\",\n\t\t\t\t`Details: ${(error as Error).message}`,\n\t\t\t].join(\"\\n\"),\n\t\t)\n\t}\n}\n\nfunction createManifest(input: {\n\trunId: string\n\trepoId: string\n\trepoSlug: string\n\trepoRoot: string\n\tbranch: string\n\tgoal: string | null\n\tplanPath: string | null\n\trecommendedPlanDir: string | null\n\tmode: \"single-pi\"\n\tleasePath: string\n}): RunManifest {\n\treturn {\n\t\trunId: input.runId,\n\t\trepoId: input.repoId,\n\t\trepoSlug: input.repoSlug,\n\t\trepoRoot: input.repoRoot,\n\t\tbranch: input.branch,\n\t\tgoal: input.goal,\n\t\tplanPath: input.planPath,\n\t\trecommendedPlanDir: input.recommendedPlanDir,\n\t\tmode: input.mode,\n\t\tstartedAt: new Date().toISOString(),\n\t\tendedAt: null,\n\t\tstopReason: null,\n\t\tleasePath: input.leasePath,\n\t\tpiExitCode: null,\n\t\tcompletedTaskCount: 0,\n\t\tblockedTaskCount: 0,\n\t\tskippedTaskCount: 0,\n\t\ttotalCostUsd: 0,\n\t}\n}\n\nfunction createSummary(input: {\n\trunId: string\n\tmode: \"single-pi\"\n\texitCode: number\n\trecommendedPlanDir: string | null\n}): RunSummary {\n\tconst success = input.exitCode === 0\n\tconst recommendation =\n\t\tinput.recommendedPlanDir === null\n\t\t\t? \"\"\n\t\t\t: ` No plan path was configured. Recommended private plans location: ${input.recommendedPlanDir}.`\n\n\treturn {\n\t\trunId: input.runId,\n\t\tmode: input.mode,\n\t\tcreatedAt: new Date().toISOString(),\n\t\tsuccess,\n\t\tmessage: success ? `Pi invocation completed.${recommendation}` : `Pi invocation failed.${recommendation}`,\n\t\tpiExitCode: input.exitCode,\n\t\trecommendedPlanDir: input.recommendedPlanDir,\n\t}\n}\n\nexport function runController(options: RunOptions): ControllerRunResult {\n\tconst cwd = options.cwd ?? process.cwd()\n\tconst artifactsDir = options.artifactsDir\n\tconst repoRoot = getRepoRoot(cwd)\n\tconst repoId = getRepoIdentity(repoRoot)\n\tconst repoSlug = createRepoSlug(repoId, repoRoot)\n\tconst branch = options.branch ?? getCurrentBranch(repoRoot) ?? \"workspace\"\n\tconst goal = options.goal ?? null\n\tconst planPath = options.planPath ?? null\n\tconst recommendedPlanDir = planPath ? null : (options.recommendedPlanDir ?? null)\n\tconst mode = options.mode ?? \"single-pi\"\n\tconst piCommand = options.piCommand ?? \"pi\"\n\tconst runId = createRunId()\n\tconst runDir = join(artifactsDir, \"runs\", runId)\n\tconst latestDir = join(artifactsDir, \"latest\")\n\tconst stdoutPath = join(runDir, \"stdout.txt\")\n\tconst stderrPath = join(runDir, \"stderr.txt\")\n\tconst prompt = createPiPrompt({ repoRoot, planPath, goal, recommendedPlanDir })\n\n\tassertPiRuntimeAvailable(piCommand)\n\n\tmkdirSync(runDir, { recursive: true })\n\tmkdirSync(latestDir, { recursive: true })\n\n\twriteText(join(runDir, \"questions.jsonl\"), \"\")\n\twriteText(join(runDir, \"interventions.jsonl\"), \"\")\n\twriteJson(join(runDir, \"agent-state.json\"), {\n\t\tstatus: \"starting\",\n\t\tupdatedAt: new Date().toISOString(),\n\t})\n\n\tconst lease = acquireRepoLease(runId, repoId, branch)\n\n\ttry {\n\t\tconst manifest = createManifest({\n\t\t\trunId,\n\t\t\trepoId,\n\t\t\trepoSlug,\n\t\t\trepoRoot,\n\t\t\tbranch,\n\t\t\tgoal,\n\t\t\tplanPath,\n\t\t\trecommendedPlanDir,\n\t\t\tmode,\n\t\t\tleasePath: lease.path,\n\t\t})\n\n\t\tappendJsonl(join(runDir, \"events.jsonl\"), {\n\t\t\ttype: \"run_started\",\n\t\t\trunId,\n\t\t\trepoId,\n\t\t\trepoSlug,\n\t\t\tbranch,\n\t\t\tcreatedAt: manifest.startedAt,\n\t\t})\n\n\t\tconst piStartedAt = new Date().toISOString()\n\t\tappendJsonl(join(runDir, \"events.jsonl\"), {\n\t\t\ttype: \"pi_invocation_started\",\n\t\t\trunId,\n\t\t\tcommand: piCommand,\n\t\t\tcreatedAt: piStartedAt,\n\t\t})\n\n\t\tconst piResult = runCommandSync(piCommand, [\"--no-session\", \"-p\", prompt], {\n\t\t\tcwd: repoRoot,\n\t\t\tenv: process.env,\n\t\t})\n\t\tconst piEndedAt = new Date().toISOString()\n\n\t\twriteText(stdoutPath, piResult.stdout)\n\t\twriteText(stderrPath, piResult.stderr)\n\n\t\tconst piInvocation: PiInvocationRecord = {\n\t\t\tcommand: piCommand,\n\t\t\tcwd: repoRoot,\n\t\t\trepoRoot,\n\t\t\tplanPath,\n\t\t\tgoal,\n\t\t\tstartedAt: piStartedAt,\n\t\t\tendedAt: piEndedAt,\n\t\t\texitCode: piResult.exitCode,\n\t\t\tstdoutPath,\n\t\t\tstderrPath,\n\t\t\tpromptSummary: planPath\n\t\t\t\t? \"Read private plan path and continue from current scaffold state.\"\n\t\t\t\t: \"Continue from current scaffold state without a configured private plan path.\",\n\t\t}\n\t\twriteJson(join(runDir, \"pi-invocation.json\"), piInvocation)\n\n\t\tappendJsonl(join(runDir, \"events.jsonl\"), {\n\t\t\ttype: \"pi_invocation_finished\",\n\t\t\trunId,\n\t\t\tcommand: piCommand,\n\t\t\texitCode: piInvocation.exitCode,\n\t\t\tcreatedAt: piEndedAt,\n\t\t})\n\n\t\tconst metrics = computeMetrics({\n\t\t\ttaskAttempts: [],\n\t\t\tinterrupts: [],\n\t\t})\n\t\tconst summary = createSummary({\n\t\t\trunId,\n\t\t\tmode,\n\t\t\texitCode: piInvocation.exitCode,\n\t\t\trecommendedPlanDir,\n\t\t})\n\t\tconst finalManifest: RunManifest = {\n\t\t\t...manifest,\n\t\t\tendedAt: piEndedAt,\n\t\t\tstopReason:\n\t\t\t\tpiInvocation.exitCode === 0\n\t\t\t\t\t? \"pi invocation completed\"\n\t\t\t\t\t: `pi invocation exited with code ${piInvocation.exitCode}`,\n\t\t\tpiExitCode: piInvocation.exitCode,\n\t\t}\n\n\t\twriteJson(join(runDir, \"manifest.json\"), finalManifest)\n\t\twriteJson(join(runDir, \"metrics.json\"), metrics)\n\t\twriteJson(join(runDir, \"run-summary.json\"), summary)\n\t\twriteJson(join(runDir, \"agent-state.json\"), {\n\t\t\tstatus: summary.success ? \"completed\" : \"failed\",\n\t\t\tupdatedAt: piEndedAt,\n\t\t\texitCode: piInvocation.exitCode,\n\t\t})\n\t\twriteJson(join(latestDir, \"manifest.json\"), finalManifest)\n\t\twriteJson(join(latestDir, \"metrics.json\"), metrics)\n\t\twriteJson(join(latestDir, \"run-summary.json\"), summary)\n\n\t\tappendJsonl(join(runDir, \"events.jsonl\"), {\n\t\t\ttype: \"run_finished\",\n\t\t\trunId,\n\t\t\tcreatedAt: finalManifest.endedAt,\n\t\t\tstopReason: finalManifest.stopReason,\n\t\t\tmetrics,\n\t\t})\n\n\t\treturn {\n\t\t\trunId,\n\t\t\trunDir,\n\t\t\tlatestDir,\n\t\t\tmanifest: finalManifest,\n\t\t\tmetrics,\n\t\t\tsummary,\n\t\t\tpiInvocation,\n\t\t}\n\t} finally {\n\t\tlease.release()\n\t}\n}\n"],"mappings":"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"}
|