feat(start-work): use getWorkResumeOptions for multi-work resume selection
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
import { statSync } from "node:fs"
|
||||
import {
|
||||
appendSessionId,
|
||||
clearBoulderState,
|
||||
addBoulderWork,
|
||||
createBoulderState,
|
||||
findPrometheusPlans,
|
||||
getActiveWorks,
|
||||
getPlanName,
|
||||
getPlanProgress,
|
||||
getWorkByPlanName,
|
||||
getWorkResumeOptions,
|
||||
readBoulderState,
|
||||
resolveBoulderPlanPath,
|
||||
selectActiveWork,
|
||||
writeBoulderState,
|
||||
} from "../../features/boulder-state"
|
||||
import { log } from "../../shared/logger"
|
||||
@@ -99,9 +103,73 @@ Ask the user which plan to work on.`
|
||||
No incomplete plans available. Create a new plan using the Prometheus agent.`
|
||||
}
|
||||
|
||||
function formatElapsedHuman(elapsedMs: number | undefined): string {
|
||||
if (typeof elapsedMs !== "number" || elapsedMs <= 0) {
|
||||
return "running"
|
||||
}
|
||||
|
||||
const totalSeconds = Math.floor(elapsedMs / 1000)
|
||||
const seconds = totalSeconds % 60
|
||||
const totalMinutes = Math.floor(totalSeconds / 60)
|
||||
const minutes = totalMinutes % 60
|
||||
const hours = Math.floor(totalMinutes / 60)
|
||||
if (hours > 0) {
|
||||
return `${hours}h ${minutes}m ${seconds}s`
|
||||
}
|
||||
if (minutes > 0) {
|
||||
return `${minutes}m ${seconds}s`
|
||||
}
|
||||
return `${seconds}s`
|
||||
}
|
||||
|
||||
function buildMultipleActiveWorksContext(params: {
|
||||
resumeOptions: ReturnType<typeof getWorkResumeOptions>
|
||||
sessionId: string
|
||||
timestamp: string
|
||||
}): string {
|
||||
const { resumeOptions, sessionId, timestamp } = params
|
||||
const optionList = resumeOptions
|
||||
.map((option, index) => `${index + 1}. ${option.plan_name} - ${option.progress.completed}/${option.progress.total} (${option.progress.total === 0 ? 0 : Math.floor((option.progress.completed / option.progress.total) * 100)}%) - elapsed: ${formatElapsedHuman(option.elapsed_ms)} - worktree: ${option.worktree_path ?? "current directory"} - sessions: ${option.session_count}`)
|
||||
.join("\n")
|
||||
|
||||
return `
|
||||
<system-reminder>
|
||||
## Multiple Active Works Found
|
||||
|
||||
Current Time: ${timestamp}
|
||||
Session ID: ${sessionId}
|
||||
|
||||
${optionList}
|
||||
|
||||
Use the Question tool to ask the user which plan to resume.
|
||||
- If the user chooses one option, run /start-work {plan-name} for that plan.
|
||||
- If the user chooses to start a new plan, proceed with cold-start auto-selection flow.
|
||||
</system-reminder>`
|
||||
}
|
||||
|
||||
function createNewWorkOrInitialize(params: {
|
||||
directory: string
|
||||
planPath: string
|
||||
sessionId: string
|
||||
activeAgent: string
|
||||
worktreePath: string | undefined
|
||||
}): void {
|
||||
const { directory, planPath, sessionId, activeAgent, worktreePath } = params
|
||||
const created = addBoulderWork(directory, {
|
||||
planPath,
|
||||
sessionId,
|
||||
agent: activeAgent,
|
||||
worktreePath,
|
||||
})
|
||||
|
||||
if (!created) {
|
||||
const initializedState = createBoulderState(planPath, sessionId, activeAgent, worktreePath)
|
||||
writeBoulderState(directory, initializedState)
|
||||
}
|
||||
}
|
||||
|
||||
function buildExplicitPlanContext(params: {
|
||||
explicitPlanName: string
|
||||
existingState: ReturnType<typeof readBoulderState>
|
||||
sessionId: string
|
||||
timestamp: string
|
||||
activeAgent: string
|
||||
@@ -109,9 +177,24 @@ function buildExplicitPlanContext(params: {
|
||||
worktreeBlock: string
|
||||
directory: string
|
||||
}): string {
|
||||
const { explicitPlanName, existingState, sessionId, timestamp, activeAgent, worktreePath, worktreeBlock, directory } = params
|
||||
const { explicitPlanName, sessionId, timestamp, activeAgent, worktreePath, worktreeBlock, directory } = params
|
||||
log(`[${HOOK_NAME}] Explicit plan name requested: ${explicitPlanName}`, { sessionID: sessionId })
|
||||
|
||||
const matchedWork = getWorkByPlanName(directory, explicitPlanName, { worktreePath })
|
||||
if (matchedWork) {
|
||||
const selectedState = selectActiveWork(directory, matchedWork.work_id)
|
||||
if (selectedState) {
|
||||
return buildExistingSessionContext({
|
||||
existingState: selectedState,
|
||||
sessionId,
|
||||
activeAgent,
|
||||
worktreePath,
|
||||
worktreeBlock,
|
||||
directory,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const allPlans = findPrometheusPlans(directory)
|
||||
const matchedPlan = findPlanByName(allPlans, explicitPlanName)
|
||||
if (!matchedPlan) {
|
||||
@@ -127,9 +210,13 @@ function buildExplicitPlanContext(params: {
|
||||
All ${progress.total} tasks are done. Create a new plan using the Prometheus agent.`
|
||||
}
|
||||
|
||||
if (existingState) {
|
||||
clearBoulderState(directory)
|
||||
}
|
||||
createNewWorkOrInitialize({
|
||||
directory,
|
||||
planPath: matchedPlan,
|
||||
sessionId,
|
||||
activeAgent,
|
||||
worktreePath,
|
||||
})
|
||||
|
||||
return buildAutoSelectedPlanContext({
|
||||
planPath: matchedPlan,
|
||||
@@ -287,11 +374,48 @@ export function buildStartWorkContextInfo(params: {
|
||||
}): string {
|
||||
const { ctx, explicitPlanName, existingState, sessionId, timestamp, activeAgent, worktreePath, worktreeBlock } = params
|
||||
|
||||
const resumeOptions = getWorkResumeOptions(ctx.directory)
|
||||
.filter((option) => option.status === "active" || option.status === "paused")
|
||||
|
||||
if (!explicitPlanName && resumeOptions.length > 1) {
|
||||
return buildMultipleActiveWorksContext({
|
||||
resumeOptions,
|
||||
sessionId,
|
||||
timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
if (!explicitPlanName && resumeOptions.length === 1) {
|
||||
const onlyOption = resumeOptions[0]
|
||||
const selectedState = selectActiveWork(ctx.directory, onlyOption.work_id)
|
||||
if (selectedState) {
|
||||
return buildExistingSessionContext({
|
||||
existingState: selectedState,
|
||||
sessionId,
|
||||
activeAgent,
|
||||
worktreePath,
|
||||
worktreeBlock,
|
||||
directory: ctx.directory,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (!explicitPlanName && resumeOptions.length === 0 && getActiveWorks(ctx.directory).length === 0) {
|
||||
return buildPlanDiscoveryContext({
|
||||
contextInfo: "",
|
||||
sessionId,
|
||||
timestamp,
|
||||
activeAgent,
|
||||
worktreePath,
|
||||
worktreeBlock,
|
||||
directory: ctx.directory,
|
||||
})
|
||||
}
|
||||
|
||||
let contextInfo = ""
|
||||
if (explicitPlanName) {
|
||||
contextInfo = buildExplicitPlanContext({
|
||||
explicitPlanName,
|
||||
existingState,
|
||||
sessionId,
|
||||
timestamp,
|
||||
activeAgent,
|
||||
|
||||
Reference in New Issue
Block a user