MCPcopy
hub / github.com/codeaashu/claude-code / call

Function call

src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts:243–418  ·  view source on GitHub ↗
(input, context)

Source from the content-addressed store, hash-verified

241 renderToolResultMessage,
242 renderToolUseRejectedMessage,
243 async call(input, context) {
244 const isAgent = !!context.agentId
245
246 const filePath = getPlanFilePath(context.agentId)
247 // CCR web UI may send an edited plan via permissionResult.updatedInput.
248 // queryHelpers.ts full-replaces finalInput, so when CCR sends {} (no edit)
249 // input.plan is undefined -> disk fallback. The internal inputSchema omits
250 // `plan` (normally injected by normalizeToolInput), hence the narrowing.
251 const inputPlan =
252 'plan' in input && typeof input.plan === 'string' ? input.plan : undefined
253 const plan = inputPlan ?? getPlan(context.agentId)
254
255 // Sync disk so VerifyPlanExecution / Read see the edit. Re-snapshot
256 // after: the only other persistFileSnapshotIfRemote call (api.ts) runs
257 // in normalizeToolInput, pre-permission — it captured the old plan.
258 if (inputPlan !== undefined && filePath) {
259 await writeFile(filePath, inputPlan, 'utf-8').catch(e => logError(e))
260 void persistFileSnapshotIfRemote()
261 }
262
263 // Check if this is a teammate that requires leader approval
264 if (isTeammate() && isPlanModeRequired()) {
265 // Plan is required for plan_mode_required teammates
266 if (!plan) {
267 throw new Error(
268 `No plan file found at ${filePath}. Please write your plan to this file before calling ExitPlanMode.`,
269 )
270 }
271 const agentName = getAgentName() || 'unknown'
272 const teamName = getTeamName()
273 const requestId = generateRequestId(
274 'plan_approval',
275 formatAgentId(agentName, teamName || 'default'),
276 )
277
278 const approvalRequest = {
279 type: 'plan_approval_request',
280 from: agentName,
281 timestamp: new Date().toISOString(),
282 planFilePath: filePath,
283 planContent: plan,
284 requestId,
285 }
286
287 await writeToMailbox(
288 'team-lead',
289 {
290 from: agentName,
291 text: jsonStringify(approvalRequest),
292 timestamp: new Date().toISOString(),
293 },
294 teamName,
295 )
296
297 // Update task state to show awaiting approval (for in-process teammates)
298 const appState = context.getAppState()
299 const agentTaskId = findInProcessTeammateTaskId(agentName, appState)
300 if (agentTaskId) {

Callers

nothing calls this directly

Calls 15

getPlanFilePathFunction · 0.85
getPlanFunction · 0.85
isTeammateFunction · 0.85
isPlanModeRequiredFunction · 0.85
getAgentNameFunction · 0.85
getTeamNameFunction · 0.85
formatAgentIdFunction · 0.85
writeToMailboxFunction · 0.85
jsonStringifyFunction · 0.85
setAwaitingPlanApprovalFunction · 0.85

Tested by

no test coverage detected