馃惐 Medium-horizon agent planning MCP server
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 121 lines 3.1 kB view raw
1/** 2 * 9plan_queue_pull tool 3 * 4 * Removes the front plan from queue and marks it active. 5 */ 6 7import type { SessionStoreInterface } from "../types.js"; 8import { formatResponse, NinePlanError } from "../types.js"; 9 10// Input schema (no required inputs) 11export const queuePullInputSchema = {}; 12 13// Input type 14export type QueuePullInput = Record<string, never>; 15 16/** 17 * Handle queue pull tool call 18 */ 19export function handleQueuePull( 20 store: SessionStoreInterface, 21 sessionName: string, 22 _args: QueuePullInput, 23): { content: { type: "text"; text: string }[] } { 24 try { 25 const plan = store.pullPlan(); 26 const planPath = store.getSessionPath() + `/plans/${plan.id}.txt`; 27 28 // Format plan content for display 29 const planContent = `## Context 30${plan.context ?? "(none)"} 31 32## Goal 33${plan.goal} 34 35## Inputs 36${plan.inputs ?? "(none)"} 37 38## Outputs 39${plan.outputs ?? "(none)"} 40 41## Approach 42${plan.approach ?? "(none)"} 43 44## Testing 45${plan.testing ?? "(none)"} 46 47## Success Criteria 48${plan.successCriteria ?? "(none)"} 49 50## Notes 51${plan.notes ?? "(none)"}`; 52 53 const response = formatResponse( 54 sessionName, 55 `Active plan: ${plan.id} 56Path: ${planPath} 57 58${planContent} 59 60--- 61Review for any ambiguities before starting execution. 62If the plan has inputs from other plans, use 9plan_history_search to find their outputs. 63If the plan's Notes indicate it was previously decomposed, use 9plan_history_get to retrieve child outcomes.`, 64 ); 65 66 return { 67 content: [{ type: "text", text: response }], 68 }; 69 } catch (error) { 70 if (error instanceof NinePlanError) { 71 // Special handling for queue empty (not really an error) 72 if (error.category === "QUEUE_EMPTY") { 73 const completedCount = store.getCompletedCount(); 74 const response = formatResponse( 75 sessionName, 76 `Queue is empty. Task complete! 77 78Completed plans: ${String(completedCount)} 79 80Use 9plan_history_search to review what was accomplished.`, 81 ); 82 return { 83 content: [{ type: "text", text: response }], 84 }; 85 } 86 87 // Special handling for plan already active 88 if (error.category === "PLAN_ALREADY_ACTIVE") { 89 const active = store.getActivePlan(); 90 if (active) { 91 const activePath = store.getSessionPath() + `/plans/${active.id}.txt`; 92 const response = formatResponse( 93 sessionName, 94 `Error: Cannot pull - a plan is already active 95 96Active plan: ${active.id} 97Path: ${activePath} 98 99Complete, defer, or discard the active plan before pulling another.`, 100 ); 101 return { 102 content: [{ type: "text", text: response }], 103 }; 104 } 105 } 106 107 return { 108 content: [{ type: "text", text: error.format(sessionName) }], 109 }; 110 } 111 throw error; 112 } 113} 114 115// Tool configuration for registration 116export const queuePullToolConfig = { 117 title: "Pull Plan from Queue", 118 description: 119 "Removes the front plan from queue and marks it as active. Returns the plan ID and file path. Only one plan can be active at a time.", 120 inputSchema: queuePullInputSchema, 121};