@within-7/minto 0.3.9 → 0.3.10

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.
Files changed (141) hide show
  1. package/dist/commands/agents/AgentsCommand.js +459 -655
  2. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  3. package/dist/commands/agents/types.js +1 -0
  4. package/dist/commands/agents/types.js.map +2 -2
  5. package/dist/commands/agents/utils/fileOperations.js +96 -36
  6. package/dist/commands/agents/utils/fileOperations.js.map +3 -3
  7. package/dist/commands/agents/utils/index.js +3 -1
  8. package/dist/commands/agents/utils/index.js.map +2 -2
  9. package/dist/commands/context.js +54 -23
  10. package/dist/commands/context.js.map +2 -2
  11. package/dist/commands/export.js +673 -93
  12. package/dist/commands/export.js.map +2 -2
  13. package/dist/commands/language.js +19 -46
  14. package/dist/commands/language.js.map +2 -2
  15. package/dist/commands/mcp-interactive.js +419 -217
  16. package/dist/commands/mcp-interactive.js.map +2 -2
  17. package/dist/commands/model.js +415 -66
  18. package/dist/commands/model.js.map +2 -2
  19. package/dist/commands/permissions.js +75 -49
  20. package/dist/commands/permissions.js.map +2 -2
  21. package/dist/commands/plugin.js +882 -185
  22. package/dist/commands/plugin.js.map +3 -3
  23. package/dist/commands/resume.js +1 -1
  24. package/dist/commands/resume.js.map +1 -1
  25. package/dist/commands/sandbox.js +168 -70
  26. package/dist/commands/sandbox.js.map +2 -2
  27. package/dist/commands/setup.js +593 -107
  28. package/dist/commands/setup.js.map +2 -2
  29. package/dist/commands/stats.js +188 -131
  30. package/dist/commands/stats.js.map +2 -2
  31. package/dist/commands/status.js +75 -13
  32. package/dist/commands/status.js.map +2 -2
  33. package/dist/commands/undo.js +138 -174
  34. package/dist/commands/undo.js.map +2 -2
  35. package/dist/commands.js.map +1 -1
  36. package/dist/components/Help.js +165 -32
  37. package/dist/components/Help.js.map +2 -2
  38. package/dist/components/InfoPanel/InfoPanel.js +123 -0
  39. package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
  40. package/dist/components/InfoPanel/index.js +5 -0
  41. package/dist/components/InfoPanel/index.js.map +7 -0
  42. package/dist/components/InfoPanel/types.js +1 -0
  43. package/dist/components/InfoPanel/types.js.map +7 -0
  44. package/dist/components/ModelSelector/BrandTextInput.js +43 -0
  45. package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
  46. package/dist/components/ModelSelector/ModelSelector.js +419 -501
  47. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  48. package/dist/components/ModelSelector/WizardContainer.js +45 -0
  49. package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
  50. package/dist/components/ModelSelector/index.js +1 -3
  51. package/dist/components/ModelSelector/index.js.map +2 -2
  52. package/dist/components/PromptInput.js +5 -5
  53. package/dist/components/PromptInput.js.map +2 -2
  54. package/dist/components/SimpleSelector/SimpleSelector.js +154 -0
  55. package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
  56. package/dist/components/SimpleSelector/index.js +5 -0
  57. package/dist/components/SimpleSelector/index.js.map +7 -0
  58. package/dist/components/SimpleSelector/types.js +1 -0
  59. package/dist/components/SimpleSelector/types.js.map +7 -0
  60. package/dist/components/StatusOverlayContent.js +21 -0
  61. package/dist/components/StatusOverlayContent.js.map +7 -0
  62. package/dist/components/TabbedListView/ScrollableList.js +31 -5
  63. package/dist/components/TabbedListView/ScrollableList.js.map +2 -2
  64. package/dist/components/TabbedListView/TabbedListView.js +122 -47
  65. package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
  66. package/dist/core/backupHook.js +29 -0
  67. package/dist/core/backupHook.js.map +7 -0
  68. package/dist/core/config/defaults.js +8 -2
  69. package/dist/core/config/defaults.js.map +2 -2
  70. package/dist/core/config/schema.js +14 -2
  71. package/dist/core/config/schema.js.map +2 -2
  72. package/dist/core/costTracker.js +0 -16
  73. package/dist/core/costTracker.js.map +2 -2
  74. package/dist/cost-tracker.js +0 -16
  75. package/dist/cost-tracker.js.map +2 -2
  76. package/dist/entrypoints/bootstrap.js +3 -1
  77. package/dist/entrypoints/bootstrap.js.map +2 -2
  78. package/dist/entrypoints/cli.js +32 -0
  79. package/dist/entrypoints/cli.js.map +2 -2
  80. package/dist/i18n/locales/en.js +300 -1
  81. package/dist/i18n/locales/en.js.map +2 -2
  82. package/dist/i18n/locales/zh-CN.js +301 -2
  83. package/dist/i18n/locales/zh-CN.js.map +2 -2
  84. package/dist/i18n/types.js.map +1 -1
  85. package/dist/services/customCommands.js +30 -8
  86. package/dist/services/customCommands.js.map +2 -2
  87. package/dist/services/plugins/lspServers.js +1 -1
  88. package/dist/services/plugins/lspServers.js.map +2 -2
  89. package/dist/services/plugins/pluginRuntime.js +2 -1
  90. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  91. package/dist/services/plugins/pluginValidation.js +10 -3
  92. package/dist/services/plugins/pluginValidation.js.map +2 -2
  93. package/dist/services/plugins/skillMarketplace.js +16 -8
  94. package/dist/services/plugins/skillMarketplace.js.map +2 -2
  95. package/dist/services/systemReminder.js +17 -6
  96. package/dist/services/systemReminder.js.map +2 -2
  97. package/dist/tools/FileEditTool/FileEditTool.js +7 -0
  98. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  99. package/dist/tools/FileWriteTool/FileWriteTool.js +7 -0
  100. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  101. package/dist/tools/MultiEditTool/MultiEditTool.js +7 -0
  102. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  103. package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
  104. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  105. package/dist/tools/TaskTool/TaskTool.js +9 -6
  106. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  107. package/dist/types/PermissionMode.js.map +1 -1
  108. package/dist/types/plugin.js +2 -4
  109. package/dist/types/plugin.js.map +2 -2
  110. package/dist/utils/agentHookExecutor.js +1 -4
  111. package/dist/utils/agentHookExecutor.js.map +2 -2
  112. package/dist/utils/agentLoader.js +67 -13
  113. package/dist/utils/agentLoader.js.map +2 -2
  114. package/dist/utils/agentMemory.js.map +2 -2
  115. package/dist/utils/claudeCodeSync.js +439 -0
  116. package/dist/utils/claudeCodeSync.js.map +7 -0
  117. package/dist/utils/config.js +1 -23
  118. package/dist/utils/config.js.map +2 -2
  119. package/dist/utils/execFileNoThrow.js +2 -1
  120. package/dist/utils/execFileNoThrow.js.map +2 -2
  121. package/dist/utils/marketplaceManager.js +80 -43
  122. package/dist/utils/marketplaceManager.js.map +2 -2
  123. package/dist/utils/messages.js +2 -2
  124. package/dist/utils/messages.js.map +2 -2
  125. package/dist/utils/pluginInstaller.js +34 -24
  126. package/dist/utils/pluginInstaller.js.map +2 -2
  127. package/dist/utils/pluginLoader.js +48 -25
  128. package/dist/utils/pluginLoader.js.map +2 -2
  129. package/dist/utils/repoFetcher.js +110 -0
  130. package/dist/utils/repoFetcher.js.map +7 -0
  131. package/dist/utils/skillLoader.js +18 -6
  132. package/dist/utils/skillLoader.js.map +2 -2
  133. package/dist/utils/stringSubstitution.js +4 -5
  134. package/dist/utils/stringSubstitution.js.map +2 -2
  135. package/dist/utils/teamConfig.js +153 -13
  136. package/dist/utils/teamConfig.js.map +2 -2
  137. package/dist/utils/terminal.js +1 -1
  138. package/dist/utils/terminal.js.map +2 -2
  139. package/dist/version.js +2 -2
  140. package/dist/version.js.map +1 -1
  141. package/package.json +6 -6
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/tools/TaskTool/TaskTool.tsx"],
4
- "sourcesContent": ["import { TextBlock } from '@anthropic-ai/sdk/resources/index.mjs'\nimport chalk from 'chalk'\nimport { last, memoize } from 'lodash-es'\nimport { EOL } from 'os'\nimport React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { z } from 'zod'\nimport { Tool, ValidationResult } from '@tool'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { getAgentPrompt } from '@constants/prompts'\nimport { getContext } from '@context'\nimport { hasPermissionsToUseTool } from '@permissions'\nimport { AssistantMessage, Message as MessageType, query } from '@query'\nimport { formatDuration, formatNumber } from '@utils/format'\nimport {\n getMessagesPath,\n getNextAvailableLogSidechainNumber,\n overwriteLog,\n logError,\n} from '@utils/log'\nimport { applyMarkdown } from '@utils/markdown'\nimport {\n createAssistantMessage,\n createUserMessage,\n getLastAssistantMessageId,\n INTERRUPT_MESSAGE,\n normalizeMessages,\n} from '@utils/messages'\nimport { getModelManager } from '@utils/model'\nimport { getMaxThinkingTokens } from '@utils/thinking'\nimport { getTheme } from '@utils/theme'\nimport { generateAgentId } from '@utils/agentStorage'\nimport { debug as debugLogger } from '@utils/debugLogger'\nimport { getTaskTools, getPrompt } from './prompt'\nimport { TOOL_NAME } from './constants'\nimport {\n getActiveAgents,\n getAgentByType,\n getAvailableAgentTypes,\n} from '@utils/agentLoader'\nimport {\n createAgentTranscript,\n getAgentTranscript,\n getResumableTranscript,\n appendMessageToTranscript,\n updateAgentTranscript,\n completeAgentTranscript,\n failAgentTranscript,\n interruptAgentTranscript,\n canResumeTranscript,\n registerToolUseAgent,\n type AgentTranscript,\n} from '@utils/agentTranscripts'\n// Background agent imports removed - run_in_background feature deprecated\nimport { UserFriendlyError, formatErrorForUser } from '@utils/userFriendlyError'\nimport {\n pushAgentContext,\n popAgentContext,\n cleanupAgentStreamingState,\n} from '@components/Spinner'\nimport {\n validateAgentPermission,\n MODE_CONFIGS,\n type PermissionMode,\n} from '@minto-types/PermissionMode'\nimport {\n executeAgentHooks,\n createHookContext,\n} from '@utils/agentHookExecutor'\nimport {\n loadAgentMemory,\n saveAgentMemory,\n formatMemoryForPrompt,\n} from '@utils/agentMemory'\nimport { getSkill, loadSkillContent } from '@utils/skillLoader'\nimport { substituteVariables } from '@utils/stringSubstitution'\n\nconst inputSchema = z.object({\n description: z\n .string()\n .describe('A short (3-5 word) description of the task'),\n prompt: z.string().describe('The task for the agent to perform'),\n model_name: z\n .string()\n .optional()\n .describe(\n 'Optional: Specific model name to use for this task. If not provided, uses the default task model pointer.',\n ),\n model: z\n .enum(['sonnet', 'opus', 'haiku'])\n .optional()\n .describe(\n 'Optional model hint for this agent. Maps to configured model pointers: sonnet\u2192main, opus\u2192reasoning, haiku\u2192quick. If not specified, uses the task model pointer. Prefer haiku for quick, straightforward tasks.',\n ),\n subagent_type: z\n .string()\n .optional()\n .describe(\n 'The specialized agent type to use. MUST be an exact name from the available agents list in the tool description. Defaults to \"general-purpose\" if not specified.',\n ),\n resume: z\n .string()\n .optional()\n .describe(\n 'Optional agent ID to resume from. If provided, the agent will continue from the previous execution transcript.',\n ),\n max_turns: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n 'Maximum number of agentic turns (API round-trips) before stopping. Used internally for warmup.',\n ),\n // run_in_background parameter removed - concurrent execution is automatic\n})\n\nexport const TaskTool = {\n async prompt({ safeMode }) {\n return await getPrompt(safeMode)\n },\n name: TOOL_NAME,\n async description() {\n // Dynamically load available agent types from plugins\n const availableTypes = await getAvailableAgentTypes()\n const typesList = availableTypes.join(', ')\n return `Launch a specialized agent to handle tasks autonomously. You MUST use an exact agent type name from this list: ${typesList}. Default to \"general-purpose\" if unsure.`\n },\n inputSchema,\n\n async *call(\n {\n description,\n prompt,\n model_name,\n model,\n subagent_type,\n resume,\n max_turns,\n },\n {\n abortController,\n options: { safeMode = false, forkNumber, messageLogName, verbose },\n readFileTimestamps,\n toolUseId,\n },\n ): AsyncGenerator<\n | { type: 'result'; data: TextBlock[]; resultForAssistant?: string }\n | {\n type: 'progress'\n content: any\n normalizedMessages?: any[]\n tools?: any[]\n },\n void,\n unknown\n > {\n const startTime = Date.now()\n\n // Default to general-purpose if no subagent_type specified\n const agentType = subagent_type || 'general-purpose'\n\n // Handle resume: check if we're resuming from a previous transcript\n let resumedTranscript: AgentTranscript | null = null\n let agentId: string\n\n if (resume) {\n resumedTranscript = getResumableTranscript(resume)\n if (!resumedTranscript) {\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `Cannot resume agent '${resume}': transcript not found or not resumable (status must be 'running' or 'interrupted')`,\n },\n ] as TextBlock[],\n resultForAssistant: `Cannot resume agent '${resume}': transcript not found or not resumable`,\n }\n return\n }\n agentId = resume\n debugLogger.info('TASK_AGENT_RESUMING', {\n agentId,\n agentType: resumedTranscript.agentType,\n messageCount: resumedTranscript.messages.length,\n previousStatus: resumedTranscript.status,\n })\n } else {\n agentId = generateAgentId()\n }\n\n // Register toolUseId -> agentId mapping for UI association\n if (toolUseId) {\n registerToolUseAgent(toolUseId, agentId)\n }\n\n // \uD83D\uDD27 CRITICAL FIX: Track whether we've yielded a result to prevent UI stuck state\n let hasYieldedResult = false\n\n // Apply subagent configuration\n let effectivePrompt = prompt\n let effectiveModel = model_name || 'task'\n let toolFilter = null\n let disallowedToolFilter: string[] | null = null // Claude Code spec: disallowedTools denylist\n let temperature = undefined\n let agentMaxThinkingTokens: number | undefined = undefined\n let effectivePermissionMode: PermissionMode = 'default'\n let loadedAgentConfig: Awaited<ReturnType<typeof getAgentByType>> = null\n\n // Load agent configuration dynamically\n if (agentType) {\n const agentConfig = await getAgentByType(agentType)\n\n if (!agentConfig) {\n // If agent type not found, return helpful message instead of throwing\n const availableTypes = await getAvailableAgentTypes()\n const helpMessage = `Agent type '${agentType}' not found.\\n\\nAvailable agents:\\n${availableTypes.map(t => ` \u2022 ${t}`).join('\\n')}\\n\\nUse /agents command to manage agent configurations.`\n\n yield {\n type: 'result',\n data: [{ type: 'text', text: helpMessage }] as TextBlock[],\n resultForAssistant: helpMessage,\n }\n hasYieldedResult = true\n return\n }\n\n // Store config for later use (hooks, memory, etc.)\n loadedAgentConfig = agentConfig\n\n // Apply system prompt if configured\n if (agentConfig.systemPrompt) {\n effectivePrompt = `${agentConfig.systemPrompt}\\n\\n${prompt}`\n }\n\n // Apply model if not overridden by model_name parameter\n if (!model_name && agentConfig.model_name) {\n // Support inherit: keep pointer-based default\n if (agentConfig.model_name !== 'inherit') {\n effectiveModel = agentConfig.model_name as string\n }\n }\n\n // Store tool filter for later application\n toolFilter = agentConfig.tools\n\n // Store disallowed tools filter for later application (Claude Code spec compliance)\n if (agentConfig.disallowedTools?.length) {\n disallowedToolFilter = agentConfig.disallowedTools\n }\n\n // Apply maxThinkingTokens if configured (Claude Code spec)\n if (agentConfig.maxThinkingTokens) {\n agentMaxThinkingTokens = agentConfig.maxThinkingTokens\n }\n\n // Validate and apply permission mode (Claude Code spec)\n // Agent permission cannot exceed session permission level\n if (agentConfig.permissionMode) {\n const sessionMode: PermissionMode = safeMode ? 'plan' : 'default'\n effectivePermissionMode = validateAgentPermission(\n agentConfig.permissionMode,\n sessionMode,\n )\n }\n\n // Load agent memory if configured (Claude Code spec)\n if (agentConfig.memory) {\n try {\n const memoryContent = await loadAgentMemory(\n agentConfig.agentType,\n agentConfig.memory,\n )\n if (memoryContent) {\n // Inject memory into system prompt\n effectivePrompt =\n formatMemoryForPrompt(memoryContent, agentConfig.agentType) +\n '\\n' +\n effectivePrompt\n }\n } catch (error) {\n debugLogger.warn('TASK_AGENT_MEMORY_LOAD_FAILED', {\n agentId,\n agentType,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n // Preload skills if configured (Claude Code spec)\n if (agentConfig.skills?.length) {\n for (const skillName of agentConfig.skills) {\n try {\n const skill = getSkill(skillName)\n if (skill) {\n const skillContent = await loadSkillContent(skill)\n // Apply string substitution for skill content\n const substitutedContent = await substituteVariables(\n skillContent,\n '', // No arguments for preloaded skills\n { sessionId: agentId, cwd: process.cwd() },\n )\n effectivePrompt += `\\n\\n<preloaded-skill name=\"${skillName}\">\\n${substitutedContent}\\n</preloaded-skill>`\n }\n } catch (error) {\n debugLogger.warn('TASK_AGENT_SKILL_PRELOAD_FAILED', {\n agentId,\n skillName,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n }\n\n // Execute onStart hooks if configured (Claude Code spec)\n if (agentConfig.hooks?.onStart?.length) {\n try {\n const hookContext = createHookContext({\n sessionId: agentId,\n agentId,\n agentType,\n })\n const hookResult = await executeAgentHooks(\n 'onStart',\n agentConfig,\n hookContext,\n )\n if (!hookResult.continue) {\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `Agent ${agentType} blocked by onStart hook: ${hookResult.reason || 'Hook requested stop'}`,\n },\n ] as TextBlock[],\n resultForAssistant: `Agent blocked by onStart hook: ${hookResult.reason}`,\n }\n hasYieldedResult = true\n return\n }\n } catch (error) {\n debugLogger.warn('TASK_AGENT_ONSTART_HOOK_FAILED', {\n agentId,\n agentType,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n // Note: temperature is not currently in our agent configs\n // but could be added in the future\n }\n\n // Apply model resolution with intelligent fallback\n // Priority: model_name (explicit) > model (alias) > agent config > task pointer > main model\n if (model) {\n // Model aliases are semantic hints, not hardcoded model names\n // Map to Minto's model pointer system for proper resolution\n const modelPointerMap: Record<string, string> = {\n sonnet: 'main', // Use main model for standard tasks\n opus: 'reasoning', // Use reasoning model for complex tasks\n haiku: 'quick', // Use quick model for fast tasks\n }\n\n const pointerType = modelPointerMap[model] || 'task'\n const modelManager = getModelManager()\n const resolvedModelName = modelManager.getModelName(pointerType as any)\n\n if (resolvedModelName) {\n effectiveModel = resolvedModelName\n }\n // If resolution fails, keep the previous effectiveModel (from agent config or 'task' default)\n }\n\n // Initialize messages: either resume from transcript or start fresh\n const messages: MessageType[] = resumedTranscript\n ? [...resumedTranscript.messages]\n : [createUserMessage(effectivePrompt)]\n\n let tools = await getTaskTools(safeMode)\n\n // Apply tool filtering if specified by subagent config\n // Claude Code spec: tools (allowlist) + disallowedTools (denylist) combination\n // Priority: disallowedTools always takes precedence over tools\n if (toolFilter) {\n // Back-compat: ['*'] means all tools\n const isAllArray =\n Array.isArray(toolFilter) &&\n toolFilter.length === 1 &&\n toolFilter[0] === '*'\n if (toolFilter === '*' || isAllArray) {\n // no-op, keep all tools (allowlist permits all)\n } else if (Array.isArray(toolFilter)) {\n tools = tools.filter(tool => toolFilter.includes(tool.name))\n }\n }\n\n // Apply disallowedTools filter (denylist takes precedence over allowlist)\n if (disallowedToolFilter?.length) {\n tools = tools.filter(tool => !disallowedToolFilter!.includes(tool.name))\n }\n\n // Apply permission mode tool restrictions (Claude Code spec)\n // Some permission modes only allow specific tools\n if (effectivePermissionMode !== 'default') {\n const modeConfig = MODE_CONFIGS[effectivePermissionMode]\n if (modeConfig && modeConfig.allowedTools[0] !== '*') {\n tools = tools.filter(tool => modeConfig.allowedTools.includes(tool.name))\n }\n }\n\n // Model already resolved in effectiveModel variable above\n const modelToUse = effectiveModel\n\n // Display initial task information with separate progress lines\n if (resumedTranscript) {\n yield {\n type: 'progress',\n content: createAssistantMessage(\n `Resuming agent: ${agentType} (${agentId})`,\n ),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n yield {\n type: 'progress',\n content: createAssistantMessage(\n `Restored ${resumedTranscript.messages.length} messages, ${resumedTranscript.toolUseCount} tool uses`,\n ),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n } else {\n yield {\n type: 'progress',\n content: createAssistantMessage(`Starting agent: ${agentType}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n }\n\n yield {\n type: 'progress',\n content: createAssistantMessage(`Using model: ${modelToUse}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n yield {\n type: 'progress',\n content: createAssistantMessage(`Task: ${description}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n yield {\n type: 'progress',\n content: createAssistantMessage(\n `Prompt: ${prompt.length > 150 ? prompt.substring(0, 150) + '...' : prompt}`,\n ),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n const [taskPrompt, context, maxThinkingTokens] = await Promise.all([\n getAgentPrompt(),\n getContext(),\n getMaxThinkingTokens(messages),\n ])\n\n // Inject model context to prevent self-referential expert consultations\n taskPrompt.push(\n `\\nIMPORTANT: You are currently running as ${modelToUse}. You do not need to consult ${modelToUse} via AskExpertModel since you ARE ${modelToUse}. Complete tasks directly using your capabilities.`,\n )\n\n // Initialize tool use count (restore from transcript if resuming)\n let toolUseCount = resumedTranscript?.toolUseCount || 0\n\n const getSidechainNumber = memoize(() =>\n getNextAvailableLogSidechainNumber(messageLogName, forkNumber),\n )\n\n // Create or update transcript for this agent execution\n if (!resumedTranscript) {\n createAgentTranscript({\n agentId,\n agentType,\n toolUseId, // Include toolUseId for event-driven UI updates\n description,\n prompt,\n model: modelToUse,\n forkNumber,\n messageLogName,\n messages: [...messages],\n toolUseCount: 0,\n })\n } else {\n // Update transcript status to running when resuming\n appendMessageToTranscript(\n agentId,\n createUserMessage(`[Resumed] ${prompt}`),\n )\n }\n\n // Build query options, adding temperature if specified\n // Use agent-configured maxThinkingTokens if available, otherwise use default\n const effectiveMaxThinkingTokens =\n agentMaxThinkingTokens ?? maxThinkingTokens\n const queryOptions = {\n safeMode,\n forkNumber,\n messageLogName,\n tools,\n commands: [],\n verbose,\n maxThinkingTokens: effectiveMaxThinkingTokens,\n model: modelToUse,\n }\n\n // Add temperature if specified by subagent config\n if (temperature !== undefined) {\n queryOptions['temperature'] = temperature\n }\n\n // \uD83D\uDD27 CRITICAL FIX: Wrap entire query execution in try-catch-finally\n // This ensures we ALWAYS yield a result, even if query() throws an error\n\n // Push agent context so streaming state is isolated for this subagent\n pushAgentContext(agentId)\n\n // Track turn count for max_turns limit\n let turnCount = 0\n\n try {\n for await (const message of query(\n messages,\n taskPrompt,\n context,\n hasPermissionsToUseTool,\n {\n abortController,\n options: queryOptions,\n messageId: getLastAssistantMessageId(messages),\n agentId,\n readFileTimestamps,\n setToolJSX: () => {}, // No-op implementation for TaskTool\n },\n )) {\n messages.push(message)\n\n // Persist message to transcript for resume capability\n appendMessageToTranscript(agentId, message)\n\n overwriteLog(\n getMessagesPath(messageLogName, forkNumber, getSidechainNumber()),\n messages.filter(_ => _.type !== 'progress'),\n )\n\n if (message.type !== 'assistant') {\n continue\n }\n\n // Increment turn count for each assistant message (API round-trip)\n turnCount++\n\n // Check max_turns limit\n if (max_turns && turnCount >= max_turns) {\n debugLogger.info('TASK_AGENT_MAX_TURNS_REACHED', {\n agentId,\n turnCount,\n max_turns,\n })\n // Break out of the query loop - will proceed to normal completion handling\n break\n }\n\n // Real-time token usage update for running task display\n if (message.message.usage) {\n updateAgentTranscript(agentId, {\n tokenUsage: {\n inputTokens: message.message.usage.input_tokens,\n outputTokens: message.message.usage.output_tokens,\n cacheReadTokens: message.message.usage.cache_read_input_tokens,\n cacheCreationTokens:\n message.message.usage.cache_creation_input_tokens,\n },\n })\n }\n\n const normalizedMessages = normalizeMessages(messages)\n\n // Process tool uses and text content for better visibility\n for (const content of message.message.content) {\n if (\n content.type === 'text' &&\n content.text &&\n content.text !== INTERRUPT_MESSAGE\n ) {\n // Show agent's reasoning/responses\n const preview =\n content.text.length > 200\n ? content.text.substring(0, 200) + '...'\n : content.text\n yield {\n type: 'progress',\n content: createAssistantMessage(`${preview}`),\n normalizedMessages,\n tools,\n }\n } else if (content.type === 'tool_use') {\n toolUseCount++\n\n // Show which tool is being used with agent context\n const toolMessage = normalizedMessages.find(\n _ =>\n _.type === 'assistant' &&\n _.message.content[0]?.type === 'tool_use' &&\n _.message.content[0].id === content.id,\n ) as AssistantMessage\n\n if (toolMessage) {\n // Clone and modify the message to show agent context\n const modifiedMessage = {\n ...toolMessage,\n message: {\n ...toolMessage.message,\n content: toolMessage.message.content.map(c => {\n if (c.type === 'tool_use' && c.id === content.id) {\n // Add agent context to tool name display\n return {\n ...c,\n name: c.name, // Keep original name, UI will handle display\n }\n }\n return c\n }),\n },\n }\n\n yield {\n type: 'progress',\n content: modifiedMessage,\n normalizedMessages,\n tools,\n }\n }\n }\n }\n }\n\n const normalizedMessages = normalizeMessages(messages)\n const lastMessage = last(messages)\n if (lastMessage?.type !== 'assistant') {\n throw new Error('Last message was not an assistant message')\n }\n\n // Calculate token usage for transcript\n const tokenUsage = {\n inputTokens: lastMessage.message.usage.input_tokens,\n outputTokens: lastMessage.message.usage.output_tokens,\n cacheReadTokens: lastMessage.message.usage.cache_read_input_tokens,\n cacheCreationTokens:\n lastMessage.message.usage.cache_creation_input_tokens,\n }\n\n // Check for interrupt\n const isInterrupted = lastMessage.message.content.some(\n _ => _.type === 'text' && _.text === INTERRUPT_MESSAGE,\n )\n\n if (isInterrupted) {\n // Mark transcript as interrupted (can be resumed later)\n interruptAgentTranscript(agentId)\n debugLogger.info('TASK_AGENT_INTERRUPTED', { agentId, toolUseCount })\n } else {\n // Mark transcript as completed\n completeAgentTranscript(agentId, tokenUsage)\n debugLogger.info('TASK_AGENT_COMPLETED', { agentId, toolUseCount })\n\n // Execute onComplete hooks if configured (Claude Code spec)\n if (loadedAgentConfig?.hooks?.onComplete?.length) {\n try {\n const hookContext = createHookContext({\n sessionId: agentId,\n agentId,\n agentType,\n result: this.renderResultForAssistant(\n lastMessage.message.content.filter(_ => _.type === 'text'),\n ),\n })\n await executeAgentHooks('onComplete', loadedAgentConfig, hookContext)\n } catch (hookError) {\n debugLogger.warn('TASK_AGENT_ONCOMPLETE_HOOK_FAILED', {\n agentId,\n agentType,\n error:\n hookError instanceof Error\n ? hookError.message\n : String(hookError),\n })\n }\n }\n\n // Save agent memory if configured (Claude Code spec)\n if (loadedAgentConfig?.memory) {\n try {\n // Save the agent's final response as memory\n const finalResponse = lastMessage.message.content\n .filter(_ => _.type === 'text')\n .map(_ => (_ as { type: 'text'; text: string }).text)\n .join('\\n')\n if (finalResponse.trim()) {\n await saveAgentMemory(\n agentType,\n loadedAgentConfig.memory,\n finalResponse,\n )\n }\n } catch (memoryError) {\n debugLogger.warn('TASK_AGENT_MEMORY_SAVE_FAILED', {\n agentId,\n agentType,\n error:\n memoryError instanceof Error\n ? memoryError.message\n : String(memoryError),\n })\n }\n }\n\n const result = [\n toolUseCount === 1 ? '1 tool use' : `${toolUseCount} tool uses`,\n formatNumber(\n (lastMessage.message.usage.cache_creation_input_tokens ?? 0) +\n (lastMessage.message.usage.cache_read_input_tokens ?? 0) +\n lastMessage.message.usage.input_tokens +\n lastMessage.message.usage.output_tokens,\n ) + ' tokens',\n formatDuration(Date.now() - startTime),\n ]\n yield {\n type: 'progress',\n content: createAssistantMessage(`Done (${result.join(' \u00B7 ')})`),\n normalizedMessages,\n tools,\n }\n }\n\n // Output is an AssistantMessage, but since TaskTool is a tool, it needs\n // to serialize its response to UserMessage-compatible content.\n const data = lastMessage.message.content.filter(_ => _.type === 'text')\n\n // Include agentId in result for potential resume\n const resultWithAgentId = isInterrupted\n ? `[Interrupted - Agent ID: ${agentId}]\\n${this.renderResultForAssistant(data)}`\n : this.renderResultForAssistant(data)\n\n yield {\n type: 'result',\n data,\n resultForAssistant: resultWithAgentId,\n }\n hasYieldedResult = true\n } catch (error) {\n // \uD83D\uDD27 CRITICAL: On error, we MUST yield a result to clear UI state\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n // \uD83D\uDD27 FIX: Check if this is an AbortError (ESC interrupt)\n // AbortError indicates user interrupted, should mark as 'interrupted' not 'failed'\n const isAbortError =\n error instanceof Error &&\n (error.name === 'AbortError' ||\n error.message.includes('aborted') ||\n error.message.includes('abort'))\n\n if (isAbortError) {\n // Mark transcript as interrupted (can be resumed later)\n interruptAgentTranscript(agentId)\n debugLogger.info('TASK_AGENT_INTERRUPTED_BY_ABORT', {\n agentId,\n toolUseCount,\n })\n\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `Task [${agentType}] interrupted\\n[Agent ID: ${agentId}]`,\n },\n ] as TextBlock[],\n resultForAssistant: `Task [${agentType}] interrupted by user\\n[Agent ID: ${agentId} - can be resumed]`,\n }\n } else {\n // Convert to user-friendly error for better UX\n const friendlyError =\n error instanceof UserFriendlyError\n ? error\n : new UserFriendlyError(error, {\n operation: 'agent task',\n model: agentType,\n })\n const friendlyMessage = friendlyError.getUserMessage()\n\n logError(`TaskTool [${agentType}] error: ${errorMessage}`)\n\n // Mark transcript as failed with friendly message\n failAgentTranscript(agentId, friendlyMessage)\n debugLogger.error('TASK_AGENT_FAILED', {\n agentId,\n error: errorMessage,\n errorId: friendlyError.id,\n })\n\n // Execute onError hooks if configured (Claude Code spec)\n if (loadedAgentConfig?.hooks?.onError?.length) {\n try {\n const hookContext = createHookContext({\n sessionId: agentId,\n agentId,\n agentType,\n error: error instanceof Error ? error : new Error(String(error)),\n })\n await executeAgentHooks('onError', loadedAgentConfig, hookContext)\n } catch (hookError) {\n debugLogger.warn('TASK_AGENT_ONERROR_HOOK_FAILED', {\n agentId,\n agentType,\n error:\n hookError instanceof Error\n ? hookError.message\n : String(hookError),\n })\n }\n }\n\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `${friendlyMessage}\\n[Agent ID: ${agentId}]`,\n },\n ] as TextBlock[],\n resultForAssistant: `Task [${agentType}] failed: ${errorMessage}\\n[Agent ID: ${agentId} - can be resumed]`,\n }\n }\n hasYieldedResult = true\n } finally {\n // Pop agent context and clean up streaming state\n popAgentContext()\n cleanupAgentStreamingState(agentId)\n\n // \uD83D\uDD27 SAFETY NET: Ensure we always yield a result even in unexpected scenarios\n if (!hasYieldedResult) {\n // Mark as interrupted if we haven't yielded a result\n interruptAgentTranscript(agentId)\n\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `Task [${agentType}] terminated unexpectedly\\n[Agent ID: ${agentId}]`,\n },\n ] as TextBlock[],\n resultForAssistant: `Task [${agentType}] terminated unexpectedly\\n[Agent ID: ${agentId} - can be resumed]`,\n }\n }\n }\n },\n\n isReadOnly() {\n return true // for now...\n },\n isConcurrencySafe() {\n return true // Task tool supports concurrent execution in official implementation\n },\n async validateInput(input, context) {\n if (!input.description || typeof input.description !== 'string') {\n return {\n result: false,\n message: 'Description is required and must be a string',\n }\n }\n if (!input.prompt || typeof input.prompt !== 'string') {\n return {\n result: false,\n message: 'Prompt is required and must be a string',\n }\n }\n\n // Model validation - similar to Edit tool error handling\n if (input.model_name) {\n const modelManager = getModelManager()\n const availableModels = modelManager.getAllAvailableModelNames()\n\n if (!availableModels.includes(input.model_name)) {\n return {\n result: false,\n message: `Model '${input.model_name}' does not exist. Available models: ${availableModels.join(', ')}`,\n meta: {\n model_name: input.model_name,\n availableModels,\n },\n }\n }\n }\n\n // Validate subagent_type if provided\n if (input.subagent_type) {\n const availableTypes = await getAvailableAgentTypes()\n if (!availableTypes.includes(input.subagent_type)) {\n return {\n result: false,\n message: `Agent type '${input.subagent_type}' does not exist. Available types: ${availableTypes.join(', ')}`,\n meta: {\n subagent_type: input.subagent_type,\n availableTypes,\n },\n }\n }\n }\n\n // Validate resume parameter if provided\n if (input.resume) {\n if (!canResumeTranscript(input.resume)) {\n return {\n result: false,\n message: `Cannot resume agent '${input.resume}': transcript not found or not resumable (status must be 'running' or 'interrupted')`,\n meta: {\n resume: input.resume,\n },\n }\n }\n }\n\n return { result: true }\n },\n async isEnabled() {\n return true\n },\n userFacingName(input?: any) {\n // Return agent name with proper prefix\n const agentType = input?.subagent_type || 'general-purpose'\n return `agent-${agentType}`\n },\n needsPermissions() {\n return false\n },\n renderResultForAssistant(data: TextBlock[]) {\n return data\n .map(block => (block.type === 'text' ? block.text : ''))\n .join('\\n')\n },\n renderToolUseMessage(\n { description, prompt, model_name, subagent_type },\n { verbose },\n ) {\n if (!description || !prompt) return null\n\n const modelManager = getModelManager()\n const defaultTaskModel = modelManager.getModelName('task')\n const actualModel = model_name || defaultTaskModel\n const agentType = subagent_type || 'general-purpose'\n const promptPreview =\n prompt.length > 80 ? prompt.substring(0, 80) + '...' : prompt\n\n const theme = getTheme()\n\n if (verbose) {\n return (\n <Box flexDirection=\"column\">\n <Text>\n [{agentType}] {actualModel}: {description}\n </Text>\n <Box\n paddingLeft={2}\n borderLeftStyle=\"single\"\n borderLeftColor={theme.secondaryBorder}\n >\n <Text color={theme.secondaryText}>{promptPreview}</Text>\n </Box>\n </Box>\n )\n }\n\n // Simple display: agent type, model and description\n return `[${agentType}] ${actualModel}: ${description}`\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(content, options?: { verbose?: boolean }) {\n const theme = getTheme()\n const verbose = options?.verbose ?? false\n\n // Guard against undefined or null content\n if (!content) {\n return (\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={theme.success}>Done</Text>\n </Box>\n )\n }\n\n if (Array.isArray(content)) {\n const textBlocks = content.filter(\n (block): block is { type: 'text'; text: string } =>\n block && block.type === 'text',\n )\n const totalLength = textBlocks.reduce(\n (sum, block) => sum + (block.text?.length || 0),\n 0,\n )\n // Use exact match for interrupt detection\n const isInterrupted = content.some(\n block =>\n block && block.type === 'text' && block.text === INTERRUPT_MESSAGE,\n )\n\n if (isInterrupted) {\n return (\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={theme.error}>Interrupted by user</Text>\n </Box>\n )\n }\n\n // Extract output content for display based on verbosity\n const outputText = textBlocks.map(b => b.text).join('\\n')\n\n // Determine how much content to show based on displayMode\n // minimal/compact (verbose=false): Just show \"Task completed (X characters)\"\n // detailed (verbose=true): Show preview of the actual output\n const getOutputPreview = () => {\n if (!verbose || !outputText) return null\n const maxLen = 500\n if (outputText.length <= maxLen) return outputText\n return outputText.substring(0, maxLen) + '...'\n }\n\n const outputPreview = getOutputPreview()\n\n return (\n <Box flexDirection=\"column\">\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={theme.success}>Done</Text>\n {textBlocks.length > 0 && verbose && (\n <Text color={theme.secondaryText}> ({totalLength} chars)</Text>\n )}\n </Box>\n </Box>\n {outputPreview && (\n <Box marginTop={1} paddingLeft={4}>\n <Text color={theme.mutedText}>{outputPreview}</Text>\n </Box>\n )}\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={theme.success}>Done</Text>\n </Box>\n )\n },\n} satisfies Tool<typeof inputSchema, TextBlock[]>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { TextBlock } from '@anthropic-ai/sdk/resources/index.mjs'\nimport chalk from 'chalk'\nimport { last, memoize } from 'lodash-es'\nimport { EOL } from 'os'\nimport React, { useState, useEffect } from 'react'\nimport { Box, Text } from 'ink'\nimport { z } from 'zod'\nimport { Tool, ValidationResult } from '@tool'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { getAgentPrompt } from '@constants/prompts'\nimport { getContext } from '@context'\nimport { hasPermissionsToUseTool } from '@permissions'\nimport { AssistantMessage, Message as MessageType, query } from '@query'\nimport { formatDuration, formatNumber } from '@utils/format'\nimport {\n getMessagesPath,\n getNextAvailableLogSidechainNumber,\n overwriteLog,\n logError,\n} from '@utils/log'\nimport { applyMarkdown } from '@utils/markdown'\nimport {\n createAssistantMessage,\n createUserMessage,\n getLastAssistantMessageId,\n INTERRUPT_MESSAGE,\n normalizeMessages,\n} from '@utils/messages'\nimport { getModelManager } from '@utils/model'\nimport { getMaxThinkingTokens } from '@utils/thinking'\nimport { getTheme } from '@utils/theme'\nimport { generateAgentId } from '@utils/agentStorage'\nimport { debug as debugLogger } from '@utils/debugLogger'\nimport { getTaskTools, getPrompt } from './prompt'\nimport { TOOL_NAME } from './constants'\nimport {\n getActiveAgents,\n getAgentByType,\n getAvailableAgentTypes,\n} from '@utils/agentLoader'\nimport {\n createAgentTranscript,\n getAgentTranscript,\n getResumableTranscript,\n appendMessageToTranscript,\n updateAgentTranscript,\n completeAgentTranscript,\n failAgentTranscript,\n interruptAgentTranscript,\n canResumeTranscript,\n registerToolUseAgent,\n type AgentTranscript,\n} from '@utils/agentTranscripts'\n// Background agent imports removed - run_in_background feature deprecated\nimport { UserFriendlyError, formatErrorForUser } from '@utils/userFriendlyError'\nimport {\n pushAgentContext,\n popAgentContext,\n cleanupAgentStreamingState,\n} from '@components/Spinner'\nimport {\n validateAgentPermission,\n MODE_CONFIGS,\n type PermissionMode,\n} from '@minto-types/PermissionMode'\nimport { executeAgentHooks, createHookContext } from '@utils/agentHookExecutor'\nimport {\n loadAgentMemory,\n saveAgentMemory,\n formatMemoryForPrompt,\n} from '@utils/agentMemory'\nimport { getSkill, loadSkillContent } from '@utils/skillLoader'\nimport { substituteVariables } from '@utils/stringSubstitution'\n\nconst inputSchema = z.object({\n description: z\n .string()\n .describe('A short (3-5 word) description of the task'),\n prompt: z.string().describe('The task for the agent to perform'),\n model_name: z\n .string()\n .optional()\n .describe(\n 'Optional: Specific model name to use for this task. If not provided, uses the default task model pointer.',\n ),\n model: z\n .enum(['sonnet', 'opus', 'haiku'])\n .optional()\n .describe(\n 'Optional model hint for this agent. Maps to configured model pointers: sonnet\u2192main, opus\u2192reasoning, haiku\u2192quick. If not specified, uses the task model pointer. Prefer haiku for quick, straightforward tasks.',\n ),\n subagent_type: z\n .string()\n .optional()\n .describe(\n 'The specialized agent type to use. MUST be an exact name from the available agents list in the tool description. Defaults to \"general-purpose\" if not specified.',\n ),\n resume: z\n .string()\n .optional()\n .describe(\n 'Optional agent ID to resume from. If provided, the agent will continue from the previous execution transcript.',\n ),\n max_turns: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n 'Maximum number of agentic turns (API round-trips) before stopping. Used internally for warmup.',\n ),\n // run_in_background parameter removed - concurrent execution is automatic\n})\n\nexport const TaskTool = {\n async prompt({ safeMode }) {\n return await getPrompt(safeMode)\n },\n name: TOOL_NAME,\n async description() {\n // Dynamically load available agent types from plugins\n const availableTypes = await getAvailableAgentTypes()\n const typesList = availableTypes.join(', ')\n return `Launch a specialized agent to handle tasks autonomously. You MUST use an exact agent type name from this list: ${typesList}. Default to \"general-purpose\" if unsure.`\n },\n inputSchema,\n\n async *call(\n {\n description,\n prompt,\n model_name,\n model,\n subagent_type,\n resume,\n max_turns,\n },\n {\n abortController,\n options: { safeMode = false, forkNumber, messageLogName, verbose },\n readFileTimestamps,\n toolUseId,\n },\n ): AsyncGenerator<\n | { type: 'result'; data: TextBlock[]; resultForAssistant?: string }\n | {\n type: 'progress'\n content: any\n normalizedMessages?: any[]\n tools?: any[]\n },\n void,\n unknown\n > {\n const startTime = Date.now()\n\n // Default to general-purpose if no subagent_type specified\n const agentType = subagent_type || 'general-purpose'\n\n // Handle resume: check if we're resuming from a previous transcript\n let resumedTranscript: AgentTranscript | null = null\n let agentId: string\n\n if (resume) {\n resumedTranscript = getResumableTranscript(resume)\n if (!resumedTranscript) {\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `Cannot resume agent '${resume}': transcript not found or not resumable (status must be 'running' or 'interrupted')`,\n },\n ] as TextBlock[],\n resultForAssistant: `Cannot resume agent '${resume}': transcript not found or not resumable`,\n }\n return\n }\n agentId = resume\n debugLogger.info('TASK_AGENT_RESUMING', {\n agentId,\n agentType: resumedTranscript.agentType,\n messageCount: resumedTranscript.messages.length,\n previousStatus: resumedTranscript.status,\n })\n } else {\n agentId = generateAgentId()\n }\n\n // Register toolUseId -> agentId mapping for UI association\n if (toolUseId) {\n registerToolUseAgent(toolUseId, agentId)\n }\n\n // \uD83D\uDD27 CRITICAL FIX: Track whether we've yielded a result to prevent UI stuck state\n let hasYieldedResult = false\n\n // Apply subagent configuration\n let effectivePrompt = prompt\n let effectiveModel = model_name || 'task'\n let toolFilter = null\n let disallowedToolFilter: string[] | null = null // Claude Code spec: disallowedTools denylist\n let temperature = undefined\n let agentMaxThinkingTokens: number | undefined = undefined\n let effectivePermissionMode: PermissionMode = 'default'\n let loadedAgentConfig: Awaited<ReturnType<typeof getAgentByType>> = null\n\n // Load agent configuration dynamically\n if (agentType) {\n const agentConfig = await getAgentByType(agentType)\n\n if (!agentConfig) {\n // If agent type not found, return helpful message instead of throwing\n const availableTypes = await getAvailableAgentTypes()\n const helpMessage = `Agent type '${agentType}' not found.\\n\\nAvailable agents:\\n${availableTypes.map(t => ` \u2022 ${t}`).join('\\n')}\\n\\nUse /agents command to manage agent configurations.`\n\n yield {\n type: 'result',\n data: [{ type: 'text', text: helpMessage }] as TextBlock[],\n resultForAssistant: helpMessage,\n }\n hasYieldedResult = true\n return\n }\n\n // Store config for later use (hooks, memory, etc.)\n loadedAgentConfig = agentConfig\n\n // Apply system prompt if configured\n if (agentConfig.systemPrompt) {\n effectivePrompt = `${agentConfig.systemPrompt}\\n\\n${prompt}`\n }\n\n // Apply model if not overridden by model_name parameter\n if (!model_name && agentConfig.model_name) {\n // Support inherit: keep pointer-based default\n if (agentConfig.model_name !== 'inherit') {\n effectiveModel = agentConfig.model_name as string\n }\n }\n\n // Store tool filter for later application\n toolFilter = agentConfig.tools\n\n // Store disallowed tools filter for later application (Claude Code spec compliance)\n if (agentConfig.disallowedTools?.length) {\n disallowedToolFilter = agentConfig.disallowedTools\n }\n\n // Apply maxThinkingTokens if configured (Claude Code spec)\n if (agentConfig.maxThinkingTokens) {\n agentMaxThinkingTokens = agentConfig.maxThinkingTokens\n }\n\n // Validate and apply permission mode (Claude Code spec)\n // Agent permission cannot exceed session permission level\n if (agentConfig.permissionMode) {\n const sessionMode: PermissionMode = safeMode ? 'plan' : 'default'\n effectivePermissionMode = validateAgentPermission(\n agentConfig.permissionMode,\n sessionMode,\n )\n }\n\n // Load agent memory if configured (Claude Code spec)\n if (agentConfig.memory) {\n try {\n const memoryContent = await loadAgentMemory(\n agentConfig.agentType,\n agentConfig.memory,\n )\n if (memoryContent) {\n // Inject memory into system prompt\n effectivePrompt =\n formatMemoryForPrompt(memoryContent, agentConfig.agentType) +\n '\\n' +\n effectivePrompt\n }\n } catch (error) {\n debugLogger.warn('TASK_AGENT_MEMORY_LOAD_FAILED', {\n agentId,\n agentType,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n // Preload skills if configured (Claude Code spec)\n if (agentConfig.skills?.length) {\n for (const skillName of agentConfig.skills) {\n try {\n const skill = getSkill(skillName)\n if (skill) {\n const skillContent = await loadSkillContent(skill)\n // Apply string substitution for skill content\n const substitutedContent = await substituteVariables(\n skillContent,\n '', // No arguments for preloaded skills\n { sessionId: agentId, cwd: process.cwd() },\n )\n effectivePrompt += `\\n\\n<preloaded-skill name=\"${skillName}\">\\n${substitutedContent}\\n</preloaded-skill>`\n }\n } catch (error) {\n debugLogger.warn('TASK_AGENT_SKILL_PRELOAD_FAILED', {\n agentId,\n skillName,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n }\n\n // Execute onStart hooks if configured (Claude Code spec)\n if (agentConfig.hooks?.onStart?.length) {\n try {\n const hookContext = createHookContext({\n sessionId: agentId,\n agentId,\n agentType,\n })\n const hookResult = await executeAgentHooks(\n 'onStart',\n agentConfig,\n hookContext,\n )\n if (!hookResult.continue) {\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `Agent ${agentType} blocked by onStart hook: ${hookResult.reason || 'Hook requested stop'}`,\n },\n ] as TextBlock[],\n resultForAssistant: `Agent blocked by onStart hook: ${hookResult.reason}`,\n }\n hasYieldedResult = true\n return\n }\n } catch (error) {\n debugLogger.warn('TASK_AGENT_ONSTART_HOOK_FAILED', {\n agentId,\n agentType,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n // Note: temperature is not currently in our agent configs\n // but could be added in the future\n }\n\n // Apply model resolution with intelligent fallback\n // Priority: model_name (explicit) > model (alias) > agent config > task pointer > main model\n if (model) {\n // Model aliases are semantic hints, not hardcoded model names\n // Map to Minto's model pointer system for proper resolution\n const modelPointerMap: Record<string, string> = {\n sonnet: 'main', // Use main model for standard tasks\n opus: 'reasoning', // Use reasoning model for complex tasks\n haiku: 'quick', // Use quick model for fast tasks\n }\n\n const pointerType = modelPointerMap[model] || 'task'\n const modelManager = getModelManager()\n const resolvedModelName = modelManager.getModelName(pointerType as any)\n\n if (resolvedModelName) {\n effectiveModel = resolvedModelName\n }\n // If resolution fails, keep the previous effectiveModel (from agent config or 'task' default)\n }\n\n // Initialize messages: either resume from transcript or start fresh\n const messages: MessageType[] = resumedTranscript\n ? [...resumedTranscript.messages]\n : [createUserMessage(effectivePrompt)]\n\n let tools = await getTaskTools(safeMode)\n\n // Apply tool filtering if specified by subagent config\n // Claude Code spec: tools (allowlist) + disallowedTools (denylist) combination\n // Priority: disallowedTools always takes precedence over tools\n if (toolFilter) {\n // Back-compat: ['*'] means all tools\n const isAllArray =\n Array.isArray(toolFilter) &&\n toolFilter.length === 1 &&\n toolFilter[0] === '*'\n if (toolFilter === '*' || isAllArray) {\n // no-op, keep all tools (allowlist permits all)\n } else if (Array.isArray(toolFilter)) {\n tools = tools.filter(tool => toolFilter.includes(tool.name))\n }\n }\n\n // Apply disallowedTools filter (denylist takes precedence over allowlist)\n if (disallowedToolFilter?.length) {\n tools = tools.filter(tool => !disallowedToolFilter!.includes(tool.name))\n }\n\n // Apply permission mode tool restrictions (Claude Code spec)\n // Some permission modes only allow specific tools\n if (effectivePermissionMode !== 'default') {\n const modeConfig = MODE_CONFIGS[effectivePermissionMode]\n if (modeConfig && modeConfig.allowedTools[0] !== '*') {\n tools = tools.filter(tool =>\n modeConfig.allowedTools.includes(tool.name),\n )\n }\n }\n\n // Model already resolved in effectiveModel variable above\n const modelToUse = effectiveModel\n\n // Display initial task information with separate progress lines\n if (resumedTranscript) {\n yield {\n type: 'progress',\n content: createAssistantMessage(\n `Resuming agent: ${agentType} (${agentId})`,\n ),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n yield {\n type: 'progress',\n content: createAssistantMessage(\n `Restored ${resumedTranscript.messages.length} messages, ${resumedTranscript.toolUseCount} tool uses`,\n ),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n } else {\n yield {\n type: 'progress',\n content: createAssistantMessage(`Starting agent: ${agentType}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n }\n\n yield {\n type: 'progress',\n content: createAssistantMessage(`Using model: ${modelToUse}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n yield {\n type: 'progress',\n content: createAssistantMessage(`Task: ${description}`),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n yield {\n type: 'progress',\n content: createAssistantMessage(\n `Prompt: ${prompt.length > 150 ? prompt.substring(0, 150) + '...' : prompt}`,\n ),\n normalizedMessages: normalizeMessages(messages),\n tools,\n }\n\n const [taskPrompt, context, maxThinkingTokens] = await Promise.all([\n getAgentPrompt(),\n getContext(),\n getMaxThinkingTokens(messages),\n ])\n\n // Inject model context to prevent self-referential expert consultations\n taskPrompt.push(\n `\\nIMPORTANT: You are currently running as ${modelToUse}. You do not need to consult ${modelToUse} via AskExpertModel since you ARE ${modelToUse}. Complete tasks directly using your capabilities.`,\n )\n\n // Initialize tool use count (restore from transcript if resuming)\n let toolUseCount = resumedTranscript?.toolUseCount || 0\n\n const getSidechainNumber = memoize(() =>\n getNextAvailableLogSidechainNumber(messageLogName, forkNumber),\n )\n\n // Create or update transcript for this agent execution\n if (!resumedTranscript) {\n createAgentTranscript({\n agentId,\n agentType,\n toolUseId, // Include toolUseId for event-driven UI updates\n description,\n prompt,\n model: modelToUse,\n forkNumber,\n messageLogName,\n messages: [...messages],\n toolUseCount: 0,\n })\n } else {\n // Update transcript status to running when resuming\n appendMessageToTranscript(\n agentId,\n createUserMessage(`[Resumed] ${prompt}`),\n )\n }\n\n // Build query options, adding temperature if specified\n // Use agent-configured maxThinkingTokens if available, otherwise use default\n const effectiveMaxThinkingTokens =\n agentMaxThinkingTokens ?? maxThinkingTokens\n const queryOptions = {\n safeMode,\n forkNumber,\n messageLogName,\n tools,\n commands: [],\n verbose,\n maxThinkingTokens: effectiveMaxThinkingTokens,\n model: modelToUse,\n }\n\n // Add temperature if specified by subagent config\n if (temperature !== undefined) {\n queryOptions['temperature'] = temperature\n }\n\n // \uD83D\uDD27 CRITICAL FIX: Wrap entire query execution in try-catch-finally\n // This ensures we ALWAYS yield a result, even if query() throws an error\n\n // Push agent context so streaming state is isolated for this subagent\n pushAgentContext(agentId)\n\n // Track turn count for max_turns limit\n let turnCount = 0\n\n try {\n for await (const message of query(\n messages,\n taskPrompt,\n context,\n hasPermissionsToUseTool,\n {\n abortController,\n options: queryOptions,\n messageId: getLastAssistantMessageId(messages),\n agentId,\n readFileTimestamps,\n setToolJSX: () => {}, // No-op implementation for TaskTool\n },\n )) {\n messages.push(message)\n\n // Persist message to transcript for resume capability\n appendMessageToTranscript(agentId, message)\n\n overwriteLog(\n getMessagesPath(messageLogName, forkNumber, getSidechainNumber()),\n messages.filter(_ => _.type !== 'progress'),\n )\n\n if (message.type !== 'assistant') {\n continue\n }\n\n // Increment turn count for each assistant message (API round-trip)\n turnCount++\n\n // Check max_turns limit\n if (max_turns && turnCount >= max_turns) {\n debugLogger.info('TASK_AGENT_MAX_TURNS_REACHED', {\n agentId,\n turnCount,\n max_turns,\n })\n // Break out of the query loop - will proceed to normal completion handling\n break\n }\n\n // Real-time token usage update for running task display\n if (message.message.usage) {\n updateAgentTranscript(agentId, {\n tokenUsage: {\n inputTokens: message.message.usage.input_tokens,\n outputTokens: message.message.usage.output_tokens,\n cacheReadTokens: message.message.usage.cache_read_input_tokens,\n cacheCreationTokens:\n message.message.usage.cache_creation_input_tokens,\n },\n })\n }\n\n const normalizedMessages = normalizeMessages(messages)\n\n // Process tool uses and text content for better visibility\n for (const content of message.message.content) {\n if (\n content.type === 'text' &&\n content.text &&\n content.text !== INTERRUPT_MESSAGE\n ) {\n // Show agent's reasoning/responses\n const preview =\n content.text.length > 200\n ? content.text.substring(0, 200) + '...'\n : content.text\n yield {\n type: 'progress',\n content: createAssistantMessage(`${preview}`),\n normalizedMessages,\n tools,\n }\n } else if (content.type === 'tool_use') {\n toolUseCount++\n\n // Show which tool is being used with agent context\n const toolMessage = normalizedMessages.find(\n _ =>\n _.type === 'assistant' &&\n _.message.content[0]?.type === 'tool_use' &&\n _.message.content[0].id === content.id,\n ) as AssistantMessage\n\n if (toolMessage) {\n // Clone and modify the message to show agent context\n const modifiedMessage = {\n ...toolMessage,\n message: {\n ...toolMessage.message,\n content: toolMessage.message.content.map(c => {\n if (c.type === 'tool_use' && c.id === content.id) {\n // Add agent context to tool name display\n return {\n ...c,\n name: c.name, // Keep original name, UI will handle display\n }\n }\n return c\n }),\n },\n }\n\n yield {\n type: 'progress',\n content: modifiedMessage,\n normalizedMessages,\n tools,\n }\n }\n }\n }\n }\n\n const normalizedMessages = normalizeMessages(messages)\n const lastMessage = last(messages)\n if (lastMessage?.type !== 'assistant') {\n throw new Error('Last message was not an assistant message')\n }\n\n // Calculate token usage for transcript\n const tokenUsage = {\n inputTokens: lastMessage.message.usage.input_tokens,\n outputTokens: lastMessage.message.usage.output_tokens,\n cacheReadTokens: lastMessage.message.usage.cache_read_input_tokens,\n cacheCreationTokens:\n lastMessage.message.usage.cache_creation_input_tokens,\n }\n\n // Check for interrupt\n const isInterrupted = lastMessage.message.content.some(\n _ => _.type === 'text' && _.text === INTERRUPT_MESSAGE,\n )\n\n if (isInterrupted) {\n // Mark transcript as interrupted (can be resumed later)\n interruptAgentTranscript(agentId)\n debugLogger.info('TASK_AGENT_INTERRUPTED', { agentId, toolUseCount })\n } else {\n // Mark transcript as completed\n completeAgentTranscript(agentId, tokenUsage)\n debugLogger.info('TASK_AGENT_COMPLETED', { agentId, toolUseCount })\n\n // Execute onComplete hooks if configured (Claude Code spec)\n if (loadedAgentConfig?.hooks?.onComplete?.length) {\n try {\n const hookContext = createHookContext({\n sessionId: agentId,\n agentId,\n agentType,\n result: this.renderResultForAssistant(\n lastMessage.message.content.filter(_ => _.type === 'text'),\n ),\n })\n await executeAgentHooks(\n 'onComplete',\n loadedAgentConfig,\n hookContext,\n )\n } catch (hookError) {\n debugLogger.warn('TASK_AGENT_ONCOMPLETE_HOOK_FAILED', {\n agentId,\n agentType,\n error:\n hookError instanceof Error\n ? hookError.message\n : String(hookError),\n })\n }\n }\n\n // Save agent memory if configured (Claude Code spec)\n if (loadedAgentConfig?.memory) {\n try {\n // Save the agent's final response as memory\n const finalResponse = lastMessage.message.content\n .filter(_ => _.type === 'text')\n .map(_ => (_ as { type: 'text'; text: string }).text)\n .join('\\n')\n if (finalResponse.trim()) {\n await saveAgentMemory(\n agentType,\n loadedAgentConfig.memory,\n finalResponse,\n )\n }\n } catch (memoryError) {\n debugLogger.warn('TASK_AGENT_MEMORY_SAVE_FAILED', {\n agentId,\n agentType,\n error:\n memoryError instanceof Error\n ? memoryError.message\n : String(memoryError),\n })\n }\n }\n\n const result = [\n toolUseCount === 1 ? '1 tool use' : `${toolUseCount} tool uses`,\n formatNumber(\n (lastMessage.message.usage.cache_creation_input_tokens ?? 0) +\n (lastMessage.message.usage.cache_read_input_tokens ?? 0) +\n lastMessage.message.usage.input_tokens +\n lastMessage.message.usage.output_tokens,\n ) + ' tokens',\n formatDuration(Date.now() - startTime),\n ]\n yield {\n type: 'progress',\n content: createAssistantMessage(`Done (${result.join(' \u00B7 ')})`),\n normalizedMessages,\n tools,\n }\n }\n\n // Output is an AssistantMessage, but since TaskTool is a tool, it needs\n // to serialize its response to UserMessage-compatible content.\n const data = lastMessage.message.content.filter(_ => _.type === 'text')\n\n // Include agentId in result for potential resume\n const resultWithAgentId = isInterrupted\n ? `[Interrupted - Agent ID: ${agentId}]\\n${this.renderResultForAssistant(data)}`\n : this.renderResultForAssistant(data)\n\n yield {\n type: 'result',\n data,\n resultForAssistant: resultWithAgentId,\n }\n hasYieldedResult = true\n } catch (error) {\n // \uD83D\uDD27 CRITICAL: On error, we MUST yield a result to clear UI state\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n // \uD83D\uDD27 FIX: Check if this is an AbortError (ESC interrupt)\n // AbortError indicates user interrupted, should mark as 'interrupted' not 'failed'\n const isAbortError =\n error instanceof Error &&\n (error.name === 'AbortError' ||\n error.message.includes('aborted') ||\n error.message.includes('abort'))\n\n if (isAbortError) {\n // Mark transcript as interrupted (can be resumed later)\n interruptAgentTranscript(agentId)\n debugLogger.info('TASK_AGENT_INTERRUPTED_BY_ABORT', {\n agentId,\n toolUseCount,\n })\n\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `Task [${agentType}] interrupted\\n[Agent ID: ${agentId}]`,\n },\n ] as TextBlock[],\n resultForAssistant: `Task [${agentType}] interrupted by user\\n[Agent ID: ${agentId} - can be resumed]`,\n }\n } else {\n // Convert to user-friendly error for better UX\n const friendlyError =\n error instanceof UserFriendlyError\n ? error\n : new UserFriendlyError(error, {\n operation: 'agent task',\n model: agentType,\n })\n const friendlyMessage = friendlyError.getUserMessage()\n\n logError(`TaskTool [${agentType}] error: ${errorMessage}`)\n\n // Mark transcript as failed with friendly message\n failAgentTranscript(agentId, friendlyMessage)\n debugLogger.error('TASK_AGENT_FAILED', {\n agentId,\n error: errorMessage,\n errorId: friendlyError.id,\n })\n\n // Execute onError hooks if configured (Claude Code spec)\n if (loadedAgentConfig?.hooks?.onError?.length) {\n try {\n const hookContext = createHookContext({\n sessionId: agentId,\n agentId,\n agentType,\n error: error instanceof Error ? error : new Error(String(error)),\n })\n await executeAgentHooks('onError', loadedAgentConfig, hookContext)\n } catch (hookError) {\n debugLogger.warn('TASK_AGENT_ONERROR_HOOK_FAILED', {\n agentId,\n agentType,\n error:\n hookError instanceof Error\n ? hookError.message\n : String(hookError),\n })\n }\n }\n\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `${friendlyMessage}\\n[Agent ID: ${agentId}]`,\n },\n ] as TextBlock[],\n resultForAssistant: `Task [${agentType}] failed: ${errorMessage}\\n[Agent ID: ${agentId} - can be resumed]`,\n }\n }\n hasYieldedResult = true\n } finally {\n // Pop agent context and clean up streaming state\n popAgentContext()\n cleanupAgentStreamingState(agentId)\n\n // \uD83D\uDD27 SAFETY NET: Ensure we always yield a result even in unexpected scenarios\n if (!hasYieldedResult) {\n // Mark as interrupted if we haven't yielded a result\n interruptAgentTranscript(agentId)\n\n yield {\n type: 'result',\n data: [\n {\n type: 'text',\n text: `Task [${agentType}] terminated unexpectedly\\n[Agent ID: ${agentId}]`,\n },\n ] as TextBlock[],\n resultForAssistant: `Task [${agentType}] terminated unexpectedly\\n[Agent ID: ${agentId} - can be resumed]`,\n }\n }\n }\n },\n\n isReadOnly() {\n return true // for now...\n },\n isConcurrencySafe() {\n return true // Task tool supports concurrent execution in official implementation\n },\n async validateInput(input, context) {\n if (!input.description || typeof input.description !== 'string') {\n return {\n result: false,\n message: 'Description is required and must be a string',\n }\n }\n if (!input.prompt || typeof input.prompt !== 'string') {\n return {\n result: false,\n message: 'Prompt is required and must be a string',\n }\n }\n\n // Model validation - similar to Edit tool error handling\n if (input.model_name) {\n const modelManager = getModelManager()\n const availableModels = modelManager.getAllAvailableModelNames()\n\n if (!availableModels.includes(input.model_name)) {\n return {\n result: false,\n message: `Model '${input.model_name}' does not exist. Available models: ${availableModels.join(', ')}`,\n meta: {\n model_name: input.model_name,\n availableModels,\n },\n }\n }\n }\n\n // Validate subagent_type if provided\n if (input.subagent_type) {\n const availableTypes = await getAvailableAgentTypes()\n if (!availableTypes.includes(input.subagent_type)) {\n return {\n result: false,\n message: `Agent type '${input.subagent_type}' does not exist. Available types: ${availableTypes.join(', ')}`,\n meta: {\n subagent_type: input.subagent_type,\n availableTypes,\n },\n }\n }\n }\n\n // Validate resume parameter if provided\n if (input.resume) {\n if (!canResumeTranscript(input.resume)) {\n return {\n result: false,\n message: `Cannot resume agent '${input.resume}': transcript not found or not resumable (status must be 'running' or 'interrupted')`,\n meta: {\n resume: input.resume,\n },\n }\n }\n }\n\n return { result: true }\n },\n async isEnabled() {\n return true\n },\n userFacingName(input?: any) {\n // Return agent name with proper prefix\n const agentType = input?.subagent_type || 'general-purpose'\n return `agent-${agentType}`\n },\n needsPermissions() {\n return false\n },\n renderResultForAssistant(data: TextBlock[]) {\n return data\n .map(block => (block.type === 'text' ? block.text : ''))\n .join('\\n')\n },\n renderToolUseMessage(\n { description, prompt, model_name, subagent_type },\n { verbose },\n ) {\n if (!description || !prompt) return null\n\n const modelManager = getModelManager()\n const defaultTaskModel = modelManager.getModelName('task')\n const actualModel = model_name || defaultTaskModel\n const agentType = subagent_type || 'general-purpose'\n const promptPreview =\n prompt.length > 80 ? prompt.substring(0, 80) + '...' : prompt\n\n const theme = getTheme()\n\n if (verbose) {\n return (\n <Box flexDirection=\"column\">\n <Text>\n [{agentType}] {actualModel}: {description}\n </Text>\n <Box\n paddingLeft={2}\n borderLeftStyle=\"single\"\n borderLeftColor={theme.secondaryBorder}\n >\n <Text color={theme.secondaryText}>{promptPreview}</Text>\n </Box>\n </Box>\n )\n }\n\n // Simple display: agent type, model and description\n return `[${agentType}] ${actualModel}: ${description}`\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(content, options?: { verbose?: boolean }) {\n const theme = getTheme()\n const verbose = options?.verbose ?? false\n\n // Guard against undefined or null content\n if (!content) {\n return (\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={theme.success}>Done</Text>\n </Box>\n )\n }\n\n if (Array.isArray(content)) {\n const textBlocks = content.filter(\n (block): block is { type: 'text'; text: string } =>\n block && block.type === 'text',\n )\n const totalLength = textBlocks.reduce(\n (sum, block) => sum + (block.text?.length || 0),\n 0,\n )\n // Use exact match for interrupt detection\n const isInterrupted = content.some(\n block =>\n block && block.type === 'text' && block.text === INTERRUPT_MESSAGE,\n )\n\n if (isInterrupted) {\n return (\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={theme.error}>Interrupted by user</Text>\n </Box>\n )\n }\n\n // Extract output content for display based on verbosity\n const outputText = textBlocks.map(b => b.text).join('\\n')\n\n // Determine how much content to show based on displayMode\n // minimal/compact (verbose=false): Just show \"Task completed (X characters)\"\n // detailed (verbose=true): Show preview of the actual output\n const getOutputPreview = () => {\n if (!verbose || !outputText) return null\n const maxLen = 500\n if (outputText.length <= maxLen) return outputText\n return outputText.substring(0, maxLen) + '...'\n }\n\n const outputPreview = getOutputPreview()\n\n return (\n <Box flexDirection=\"column\">\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={theme.success}>Done</Text>\n {textBlocks.length > 0 && verbose && (\n <Text color={theme.secondaryText}> ({totalLength} chars)</Text>\n )}\n </Box>\n </Box>\n {outputPreview && (\n <Box marginTop={1} paddingLeft={4}>\n <Text color={theme.mutedText}>{outputPreview}</Text>\n </Box>\n )}\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={theme.success}>Done</Text>\n </Box>\n )\n },\n} satisfies Tool<typeof inputSchema, TextBlock[]>\n"],
5
+ "mappings": "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",
6
6
  "names": ["normalizedMessages"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/types/PermissionMode.ts"],
4
- "sourcesContent": ["// Permission mode types retained for compatibility with earlier agent implementations\n// Extended for Claude Code specification compliance\nexport type PermissionMode =\n | 'default' // Normal permission checking\n | 'acceptEdits' // Auto-approve file edit operations\n | 'dontAsk' // Trust agent, no permission prompts (Claude Code spec)\n | 'plan' // Read-only research and planning mode\n | 'bypassPermissions' // All permissions bypassed (dangerous)\n\n// Permission level hierarchy for validation\n// Lower number = more restrictive\nexport const PERMISSION_LEVELS: Record<PermissionMode, number> = {\n plan: 0,\n default: 1,\n acceptEdits: 2,\n dontAsk: 3,\n bypassPermissions: 4,\n}\n\n/**\n * Validate that agent permission mode does not exceed session permission level\n * Returns the effective permission mode (capped at session level)\n */\nexport function validateAgentPermission(\n agentMode: PermissionMode,\n sessionMode: PermissionMode,\n): PermissionMode {\n const agentLevel = PERMISSION_LEVELS[agentMode] ?? 1\n const sessionLevel = PERMISSION_LEVELS[sessionMode] ?? 1\n return agentLevel <= sessionLevel ? agentMode : sessionMode\n}\n\nexport interface PermissionContext {\n mode: PermissionMode\n allowedTools: string[]\n allowedPaths: string[]\n restrictions: {\n readOnly: boolean\n requireConfirmation: boolean\n bypassValidation: boolean\n }\n metadata: {\n activatedAt?: string\n previousMode?: PermissionMode\n transitionCount: number\n }\n}\n\nexport interface ModeConfig {\n name: PermissionMode\n label: string\n icon: string\n color: string\n description: string\n allowedTools: string[]\n restrictions: {\n readOnly: boolean\n requireConfirmation: boolean\n bypassValidation: boolean\n }\n}\n\n// Mode configuration preserved for Claude Code parity\nexport const MODE_CONFIGS: Record<PermissionMode, ModeConfig> = {\n default: {\n name: 'default',\n label: 'DEFAULT',\n icon: '\uD83D\uDD12',\n color: 'blue',\n description: 'Standard permission checking',\n allowedTools: ['*'],\n restrictions: {\n readOnly: false,\n requireConfirmation: true,\n bypassValidation: false,\n },\n },\n acceptEdits: {\n name: 'acceptEdits',\n label: 'ACCEPT EDITS',\n icon: '\u2705',\n color: 'green',\n description: 'Auto-approve edit operations',\n allowedTools: ['*'],\n restrictions: {\n readOnly: false,\n requireConfirmation: false,\n bypassValidation: false,\n },\n },\n dontAsk: {\n name: 'dontAsk',\n label: 'DONT ASK',\n icon: '\uD83E\uDD2B',\n color: 'cyan',\n description: 'Trust agent - no permission prompts (Claude Code spec)',\n allowedTools: ['*'],\n restrictions: {\n readOnly: false,\n requireConfirmation: false,\n bypassValidation: false,\n },\n },\n plan: {\n name: 'plan',\n label: 'PLAN MODE',\n icon: '\uD83D\uDCDD',\n color: 'yellow',\n description: 'Research and planning - read-only tools only',\n allowedTools: [\n 'Read',\n 'Grep',\n 'Glob',\n 'LS',\n 'WebSearch',\n 'WebFetch',\n 'NotebookRead',\n 'exit_plan_mode',\n ],\n restrictions: {\n readOnly: true,\n requireConfirmation: true,\n bypassValidation: false,\n },\n },\n bypassPermissions: {\n name: 'bypassPermissions',\n label: 'BYPASS PERMISSIONS',\n icon: '\uD83D\uDD13',\n color: 'red',\n description: 'All permissions bypassed',\n allowedTools: ['*'],\n restrictions: {\n readOnly: false,\n requireConfirmation: false,\n bypassValidation: true,\n },\n },\n}\n\n// Mode cycling function preserved from the Claude Code workflow\nexport function getNextPermissionMode(\n currentMode: PermissionMode,\n isBypassAvailable: boolean = true,\n): PermissionMode {\n switch (currentMode) {\n case 'default':\n return 'acceptEdits'\n case 'acceptEdits':\n return 'dontAsk'\n case 'dontAsk':\n return 'plan'\n case 'plan':\n return isBypassAvailable ? 'bypassPermissions' : 'default'\n case 'bypassPermissions':\n return 'default'\n default:\n return 'default'\n }\n}\n"],
4
+ "sourcesContent": ["// Permission mode types retained for compatibility with earlier agent implementations\n// Extended for Claude Code specification compliance\nexport type PermissionMode =\n | 'default' // Normal permission checking\n | 'acceptEdits' // Auto-approve file edit operations\n | 'dontAsk' // Trust agent, no permission prompts (Claude Code spec)\n | 'plan' // Read-only research and planning mode\n | 'bypassPermissions' // All permissions bypassed (dangerous)\n\n// Permission level hierarchy for validation\n// Lower number = more restrictive\nexport const PERMISSION_LEVELS: Record<PermissionMode, number> = {\n plan: 0,\n default: 1,\n acceptEdits: 2,\n dontAsk: 3,\n bypassPermissions: 4,\n}\n\n/**\n * Validate that agent permission mode does not exceed session permission level\n * Returns the effective permission mode (capped at session level)\n */\nexport function validateAgentPermission(\n agentMode: PermissionMode,\n sessionMode: PermissionMode,\n): PermissionMode {\n const agentLevel = PERMISSION_LEVELS[agentMode] ?? 1\n const sessionLevel = PERMISSION_LEVELS[sessionMode] ?? 1\n return agentLevel <= sessionLevel ? agentMode : sessionMode\n}\n\nexport interface PermissionContext {\n mode: PermissionMode\n allowedTools: string[]\n allowedPaths: string[]\n restrictions: {\n readOnly: boolean\n requireConfirmation: boolean\n bypassValidation: boolean\n }\n metadata: {\n activatedAt?: string\n previousMode?: PermissionMode\n transitionCount: number\n }\n}\n\nexport interface ModeConfig {\n name: PermissionMode\n label: string\n icon: string\n color: string\n description: string\n allowedTools: string[]\n restrictions: {\n readOnly: boolean\n requireConfirmation: boolean\n bypassValidation: boolean\n }\n}\n\n// Mode configuration preserved for Claude Code parity\nexport const MODE_CONFIGS: Record<PermissionMode, ModeConfig> = {\n default: {\n name: 'default',\n label: 'DEFAULT',\n icon: '\uD83D\uDD12',\n color: 'blue',\n description: 'Standard permission checking',\n allowedTools: ['*'],\n restrictions: {\n readOnly: false,\n requireConfirmation: true,\n bypassValidation: false,\n },\n },\n acceptEdits: {\n name: 'acceptEdits',\n label: 'ACCEPT EDITS',\n icon: '\u2705',\n color: 'green',\n description: 'Auto-approve edit operations',\n allowedTools: ['*'],\n restrictions: {\n readOnly: false,\n requireConfirmation: false,\n bypassValidation: false,\n },\n },\n dontAsk: {\n name: 'dontAsk',\n label: 'DONT ASK',\n icon: '\uD83E\uDD2B',\n color: 'cyan',\n description: 'Trust agent - no permission prompts (Claude Code spec)',\n allowedTools: ['*'],\n restrictions: {\n readOnly: false,\n requireConfirmation: false,\n bypassValidation: false,\n },\n },\n plan: {\n name: 'plan',\n label: 'PLAN MODE',\n icon: '\uD83D\uDCDD',\n color: 'yellow',\n description: 'Research and planning - read-only tools only',\n allowedTools: [\n 'Read',\n 'Grep',\n 'Glob',\n 'LS',\n 'WebSearch',\n 'WebFetch',\n 'NotebookRead',\n 'exit_plan_mode',\n ],\n restrictions: {\n readOnly: true,\n requireConfirmation: true,\n bypassValidation: false,\n },\n },\n bypassPermissions: {\n name: 'bypassPermissions',\n label: 'BYPASS PERMISSIONS',\n icon: '\uD83D\uDD13',\n color: 'red',\n description: 'All permissions bypassed',\n allowedTools: ['*'],\n restrictions: {\n readOnly: false,\n requireConfirmation: false,\n bypassValidation: true,\n },\n },\n}\n\n// Mode cycling function preserved from the Claude Code workflow\nexport function getNextPermissionMode(\n currentMode: PermissionMode,\n isBypassAvailable: boolean = true,\n): PermissionMode {\n switch (currentMode) {\n case 'default':\n return 'acceptEdits'\n case 'acceptEdits':\n return 'dontAsk'\n case 'dontAsk':\n return 'plan'\n case 'plan':\n return isBypassAvailable ? 'bypassPermissions' : 'default'\n case 'bypassPermissions':\n return 'default'\n default:\n return 'default'\n }\n}\n"],
5
5
  "mappings": "AAWO,MAAM,oBAAoD;AAAA,EAC/D,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,SAAS;AAAA,EACT,mBAAmB;AACrB;AAMO,SAAS,wBACd,WACA,aACgB;AAChB,QAAM,aAAa,kBAAkB,SAAS,KAAK;AACnD,QAAM,eAAe,kBAAkB,WAAW,KAAK;AACvD,SAAO,cAAc,eAAe,YAAY;AAClD;AAiCO,MAAM,eAAmD;AAAA,EAC9D,SAAS;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc,CAAC,GAAG;AAAA,IAClB,cAAc;AAAA,MACZ,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc,CAAC,GAAG;AAAA,IAClB,cAAc;AAAA,MACZ,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc,CAAC,GAAG;AAAA,IAClB,cAAc;AAAA,MACZ,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,cAAc;AAAA,MACZ,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EACA,mBAAmB;AAAA,IACjB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc,CAAC,GAAG;AAAA,IAClB,cAAc;AAAA,MACZ,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,kBAAkB;AAAA,IACpB;AAAA,EACF;AACF;AAGO,SAAS,sBACd,aACA,oBAA6B,MACb;AAChB,UAAQ,aAAa;AAAA,IACnB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,oBAAoB,sBAAsB;AAAA,IACnD,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;",
6
6
  "names": []
7
7
  }
@@ -24,10 +24,8 @@ const PluginManifestSchema = z.object({
24
24
  /^[a-z0-9-]+$/,
25
25
  "Plugin name must be lowercase alphanumeric with hyphens"
26
26
  ),
27
- version: z.string().regex(
28
- /^\d+\.\d+\.\d+$/,
29
- "Version must follow semver format (e.g., 1.0.0)"
30
- ),
27
+ version: z.string().min(1),
28
+ // Supports semver and commit hashes (for CC sync)
31
29
  description: z.string().min(1),
32
30
  // Optional metadata
33
31
  displayName: z.string().optional(),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/types/plugin.ts"],
4
- "sourcesContent": ["/**\n * Plugin System Type Definitions\n */\n\nimport { z } from 'zod'\n\n/**\n * Author information (can be string or object)\n */\nexport const AuthorSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n email: z.string().email().optional(),\n url: z.string().url().optional(),\n }),\n])\n\n/**\n * MCP Server Configuration Schema\n * Compatible with Claude Code CLI's .mcp.json format\n */\nexport const MCPServerConfigSchema = z.object({\n // Command-based (stdio) servers\n command: z.string().optional(),\n args: z.array(z.string()).optional().default([]),\n env: z.record(z.string()).optional().default({}),\n timeout: z.number().optional(),\n\n // HTTP/SSE servers\n type: z.enum(['stdio', 'http', 'sse']).optional().default('stdio'),\n url: z.string().optional(),\n headers: z.record(z.string()).optional(),\n})\n\nexport type MCPServerConfig = z.infer<typeof MCPServerConfigSchema>\n\n/**\n * Plugin Manifest Schema (plugin.json)\n * This is the source of truth for plugin metadata\n */\nexport const PluginManifestSchema = z.object({\n // Required fields\n name: z\n .string()\n .min(1)\n .regex(\n /^[a-z0-9-]+$/,\n 'Plugin name must be lowercase alphanumeric with hyphens',\n ),\n version: z\n .string()\n .regex(\n /^\\d+\\.\\d+\\.\\d+$/,\n 'Version must follow semver format (e.g., 1.0.0)',\n ),\n description: z.string().min(1),\n\n // Optional metadata\n displayName: z.string().optional(),\n author: AuthorSchema.optional(),\n homepage: z.string().url().optional(),\n repository: z.string().url().optional(),\n license: z.string().optional(),\n\n // Plugin components (relative paths from plugin root)\n agents: z.array(z.string()).optional().default([]),\n commands: z.array(z.string()).optional().default([]),\n skills: z.array(z.string()).optional().default([]),\n hooks: z.array(z.string()).optional().default([]),\n\n // MCP servers support both:\n // - Array of file paths: [\"mcp-servers/server1.json\"]\n // - Object with inline configs: { \"server1\": { command: \"...\" } }\n mcpServers: z\n .union([z.array(z.string()), z.record(MCPServerConfigSchema)])\n .optional()\n .default([]),\n\n // Dependencies\n dependencies: z.record(z.string()).optional().default({}),\n\n // Minto/Claude Code version requirements\n engines: z\n .object({\n minto: z.string().optional(),\n 'claude-code': z.string().optional(),\n node: z.string().optional(),\n })\n .optional(),\n\n // Plugin-specific configuration schema\n configSchema: z.record(z.any()).optional(),\n})\n\nexport type PluginManifest = z.infer<typeof PluginManifestSchema>\n\n/**\n * Loaded Plugin (runtime representation)\n */\nexport interface LoadedPlugin {\n name: string\n manifest: PluginManifest\n location: string // Absolute path to plugin directory\n source: PluginSource\n agents: LoadedAgent[]\n commands: LoadedCommand[]\n skills: LoadedSkill[]\n hooks: LoadedHook[]\n mcpServers: LoadedMCPServer[]\n enabled: boolean\n config?: Record<string, any>\n}\n\n/**\n * Plugin source types\n */\nexport type PluginSource =\n | { type: 'local'; path: string }\n | { type: 'git'; repo: string; ref?: string }\n | { type: 'npm'; package: string; version?: string }\n | { type: 'marketplace'; marketplace: string; name: string }\n\n/**\n * Agent component (from plugin)\n */\nexport interface LoadedAgent {\n name: string\n filePath: string\n config: {\n name: string\n description: string\n tools?: string | string[]\n model?: string\n content: string\n }\n pluginName: string\n}\n\n/**\n * Command component (from plugin)\n */\nexport interface LoadedCommand {\n name: string\n filePath: string\n config: {\n name: string\n description?: string\n aliases?: string[]\n enabled?: boolean\n hidden?: boolean\n progressMessage?: string\n argNames?: string[]\n 'allowed-tools'?: string[]\n content: string\n }\n pluginName: string\n}\n\n/**\n * Skill configuration (Claude Code specification compliant)\n */\nexport interface SkillConfig {\n // Identity\n name: string\n description: string\n argumentHint?: string // Hint for expected arguments\n\n // Invocation control (Claude Code spec)\n disableModelInvocation?: boolean // If true, model cannot auto-invoke (user-only)\n userInvocable?: boolean // If true, user can invoke via /command (default: true)\n\n // Execution configuration\n allowedTools?: string[] // Tools the skill can use\n model?: 'sonnet' | 'opus' | 'haiku' | 'inherit' // Model to use\n\n // Fork context (Claude Code spec)\n context?: 'fork' // Execute in isolated context\n agent?: string // Agent type to use for fork execution\n\n // Content\n content: string\n}\n\n/**\n * Skill component (from plugin or standalone)\n */\nexport interface LoadedSkill {\n name: string\n filePath: string\n config: SkillConfig\n pluginName: string // 'standalone' for standalone skills\n source: 'plugin' | 'user' | 'project' // Where the skill was loaded from\n}\n\n/**\n * Hook component (from plugin)\n */\nexport interface LoadedHook {\n name: string\n filePath: string\n config: {\n event: HookEvent\n matcher?: string\n type: 'command' | 'message' | 'notification'\n command?: string\n message?: string\n blocking?: boolean\n timeout?: number\n }\n pluginName: string\n event: HookEvent // Also store event at root level for easier access\n matcher?: string // Also store matcher at root level\n}\n\n/**\n * Hook lifecycle events\n */\nexport type HookEvent =\n | 'PreToolUse'\n | 'PostToolUse'\n | 'UserPromptSubmit'\n | 'SessionStart'\n | 'SessionEnd'\n | 'Stop'\n | 'SubagentStop'\n | 'Notification'\n | 'PreCompact'\n\n/**\n * MCP Server component (from plugin)\n */\nexport interface LoadedMCPServer {\n name: string\n filePath: string\n config: {\n command: string\n args?: string[]\n env?: Record<string, string>\n timeout?: number\n }\n pluginName: string\n}\n\n/**\n * Plugin installation options\n */\nexport interface PluginInstallOptions {\n source: PluginSource\n global?: boolean // Install globally vs project-level\n enable?: boolean // Auto-enable after install\n config?: Record<string, any> // Plugin-specific config\n}\n\n/**\n * Plugin marketplace configuration\n */\nexport interface PluginMarketplace {\n name: string\n source: PluginSource\n plugins: PluginManifest[]\n}\n\n/**\n * Plugin error types\n */\nexport class PluginError extends Error {\n constructor(\n message: string,\n public code: PluginErrorCode,\n public pluginName?: string,\n public details?: any,\n ) {\n super(message)\n this.name = 'PluginError'\n }\n}\n\nexport enum PluginErrorCode {\n MANIFEST_INVALID = 'MANIFEST_INVALID',\n MANIFEST_NOT_FOUND = 'MANIFEST_NOT_FOUND',\n VERSION_MISMATCH = 'VERSION_MISMATCH',\n DEPENDENCY_MISSING = 'DEPENDENCY_MISSING',\n COMPONENT_NOT_FOUND = 'COMPONENT_NOT_FOUND',\n COMPONENT_INVALID = 'COMPONENT_INVALID',\n ALREADY_INSTALLED = 'ALREADY_INSTALLED',\n NOT_INSTALLED = 'NOT_INSTALLED',\n PERMISSION_DENIED = 'PERMISSION_DENIED',\n}\n\n// ============================================================================\n// Session Plugin Types (Claude Code CLI Compatible)\n// ============================================================================\n\n/**\n * A loaded plugin in the current session\n * Compatible with Claude Code CLI session plugins\n */\nexport interface SessionPlugin {\n /** Plugin name from manifest */\n name: string\n /** Root directory of the plugin */\n rootDir: string\n /** Path to the manifest file */\n manifestPath: string\n /** Raw manifest data */\n manifest: unknown\n /** Directories containing custom commands */\n commandsDirs: string[]\n /** Directories containing skills */\n skillsDirs: string[]\n /** Directories containing agents */\n agentsDirs: string[]\n /** Paths to hooks configuration files */\n hooksFiles: string[]\n /** Directories containing output styles */\n outputStylesDirs: string[]\n /** Paths to MCP server configuration files */\n mcpConfigFiles: string[]\n /** Paths to LSP server configuration files (Claude Code CLI specific) */\n lspConfigFiles: string[]\n}\n\n/**\n * Plugin scope - where the plugin is installed/activated\n */\nexport type PluginScope = 'user' | 'project' | 'local'\n\n/**\n * Installed skill plugin record\n */\nexport interface InstalledSkillPlugin {\n plugin: string\n marketplace: string\n scope: PluginScope\n kind?: 'skill-pack' | 'plugin-pack'\n isEnabled?: boolean\n projectPath?: string\n installedAt: string\n pluginRoot?: string\n skills: string[]\n commands: string[]\n sourceMarketplacePath: string\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Plugin System Type Definitions\n */\n\nimport { z } from 'zod'\n\n/**\n * Author information (can be string or object)\n */\nexport const AuthorSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n email: z.string().email().optional(),\n url: z.string().url().optional(),\n }),\n])\n\n/**\n * MCP Server Configuration Schema\n * Compatible with Claude Code CLI's .mcp.json format\n */\nexport const MCPServerConfigSchema = z.object({\n // Command-based (stdio) servers\n command: z.string().optional(),\n args: z.array(z.string()).optional().default([]),\n env: z.record(z.string()).optional().default({}),\n timeout: z.number().optional(),\n\n // HTTP/SSE servers\n type: z.enum(['stdio', 'http', 'sse']).optional().default('stdio'),\n url: z.string().optional(),\n headers: z.record(z.string()).optional(),\n})\n\nexport type MCPServerConfig = z.infer<typeof MCPServerConfigSchema>\n\n/**\n * Plugin Manifest Schema (plugin.json)\n * This is the source of truth for plugin metadata\n */\nexport const PluginManifestSchema = z.object({\n // Required fields\n name: z\n .string()\n .min(1)\n .regex(\n /^[a-z0-9-]+$/,\n 'Plugin name must be lowercase alphanumeric with hyphens',\n ),\n version: z.string().min(1), // Supports semver and commit hashes (for CC sync)\n description: z.string().min(1),\n\n // Optional metadata\n displayName: z.string().optional(),\n author: AuthorSchema.optional(),\n homepage: z.string().url().optional(),\n repository: z.string().url().optional(),\n license: z.string().optional(),\n\n // Plugin components (relative paths from plugin root)\n agents: z.array(z.string()).optional().default([]),\n commands: z.array(z.string()).optional().default([]),\n skills: z.array(z.string()).optional().default([]),\n hooks: z.array(z.string()).optional().default([]),\n\n // MCP servers support both:\n // - Array of file paths: [\"mcp-servers/server1.json\"]\n // - Object with inline configs: { \"server1\": { command: \"...\" } }\n mcpServers: z\n .union([z.array(z.string()), z.record(MCPServerConfigSchema)])\n .optional()\n .default([]),\n\n // Dependencies\n dependencies: z.record(z.string()).optional().default({}),\n\n // Minto/Claude Code version requirements\n engines: z\n .object({\n minto: z.string().optional(),\n 'claude-code': z.string().optional(),\n node: z.string().optional(),\n })\n .optional(),\n\n // Plugin-specific configuration schema\n configSchema: z.record(z.any()).optional(),\n})\n\nexport type PluginManifest = z.infer<typeof PluginManifestSchema>\n\n/**\n * Loaded Plugin (runtime representation)\n */\nexport interface LoadedPlugin {\n name: string\n manifest: PluginManifest\n location: string // Absolute path to plugin directory\n source: PluginSource\n agents: LoadedAgent[]\n commands: LoadedCommand[]\n skills: LoadedSkill[]\n hooks: LoadedHook[]\n mcpServers: LoadedMCPServer[]\n enabled: boolean\n config?: Record<string, any>\n}\n\n/**\n * Plugin source types\n */\nexport type PluginSource =\n | { type: 'local'; path: string }\n | { type: 'git'; repo: string; ref?: string }\n | { type: 'npm'; package: string; version?: string }\n | { type: 'marketplace'; marketplace: string; name: string }\n | { type: 'claude-code'; marketplace: string; name: string }\n\n/**\n * Agent component (from plugin)\n */\nexport interface LoadedAgent {\n name: string\n filePath: string\n config: {\n name: string\n description: string\n tools?: string | string[]\n model?: string\n content: string\n }\n pluginName: string\n}\n\n/**\n * Command component (from plugin)\n */\nexport interface LoadedCommand {\n name: string\n filePath: string\n config: {\n name: string\n description?: string\n aliases?: string[]\n enabled?: boolean\n hidden?: boolean\n progressMessage?: string\n argNames?: string[]\n 'allowed-tools'?: string[]\n content: string\n }\n pluginName: string\n}\n\n/**\n * Skill configuration (Claude Code specification compliant)\n */\nexport interface SkillConfig {\n // Identity\n name: string\n description: string\n argumentHint?: string // Hint for expected arguments\n\n // Invocation control (Claude Code spec)\n disableModelInvocation?: boolean // If true, model cannot auto-invoke (user-only)\n userInvocable?: boolean // If true, user can invoke via /command (default: true)\n\n // Execution configuration\n allowedTools?: string[] // Tools the skill can use\n model?: 'sonnet' | 'opus' | 'haiku' | 'inherit' // Model to use\n\n // Fork context (Claude Code spec)\n context?: 'fork' // Execute in isolated context\n agent?: string // Agent type to use for fork execution\n\n // Content\n content: string\n}\n\n/**\n * Skill component (from plugin or standalone)\n */\nexport interface LoadedSkill {\n name: string\n filePath: string\n config: SkillConfig\n pluginName: string // 'standalone' for standalone skills\n source: 'plugin' | 'user' | 'project' // Where the skill was loaded from\n}\n\n/**\n * Hook component (from plugin)\n */\nexport interface LoadedHook {\n name: string\n filePath: string\n config: {\n event: HookEvent\n matcher?: string\n type: 'command' | 'message' | 'notification'\n command?: string\n message?: string\n blocking?: boolean\n timeout?: number\n }\n pluginName: string\n event: HookEvent // Also store event at root level for easier access\n matcher?: string // Also store matcher at root level\n}\n\n/**\n * Hook lifecycle events\n */\nexport type HookEvent =\n | 'PreToolUse'\n | 'PostToolUse'\n | 'UserPromptSubmit'\n | 'SessionStart'\n | 'SessionEnd'\n | 'Stop'\n | 'SubagentStop'\n | 'Notification'\n | 'PreCompact'\n\n/**\n * MCP Server component (from plugin)\n */\nexport interface LoadedMCPServer {\n name: string\n filePath: string\n config: {\n command: string\n args?: string[]\n env?: Record<string, string>\n timeout?: number\n }\n pluginName: string\n}\n\n/**\n * Plugin installation options\n */\nexport interface PluginInstallOptions {\n source: PluginSource\n global?: boolean // Install globally vs project-level\n enable?: boolean // Auto-enable after install\n config?: Record<string, any> // Plugin-specific config\n}\n\n/**\n * Plugin marketplace configuration\n */\nexport interface PluginMarketplace {\n name: string\n source: PluginSource\n plugins: PluginManifest[]\n}\n\n/**\n * Plugin error types\n */\nexport class PluginError extends Error {\n constructor(\n message: string,\n public code: PluginErrorCode,\n public pluginName?: string,\n public details?: any,\n ) {\n super(message)\n this.name = 'PluginError'\n }\n}\n\nexport enum PluginErrorCode {\n MANIFEST_INVALID = 'MANIFEST_INVALID',\n MANIFEST_NOT_FOUND = 'MANIFEST_NOT_FOUND',\n VERSION_MISMATCH = 'VERSION_MISMATCH',\n DEPENDENCY_MISSING = 'DEPENDENCY_MISSING',\n COMPONENT_NOT_FOUND = 'COMPONENT_NOT_FOUND',\n COMPONENT_INVALID = 'COMPONENT_INVALID',\n ALREADY_INSTALLED = 'ALREADY_INSTALLED',\n NOT_INSTALLED = 'NOT_INSTALLED',\n PERMISSION_DENIED = 'PERMISSION_DENIED',\n}\n\n// ============================================================================\n// Session Plugin Types (Claude Code CLI Compatible)\n// ============================================================================\n\n/**\n * A loaded plugin in the current session\n * Compatible with Claude Code CLI session plugins\n */\nexport interface SessionPlugin {\n /** Plugin name from manifest */\n name: string\n /** Root directory of the plugin */\n rootDir: string\n /** Path to the manifest file */\n manifestPath: string\n /** Raw manifest data */\n manifest: unknown\n /** Directories containing custom commands */\n commandsDirs: string[]\n /** Directories containing skills */\n skillsDirs: string[]\n /** Directories containing agents */\n agentsDirs: string[]\n /** Paths to hooks configuration files */\n hooksFiles: string[]\n /** Directories containing output styles */\n outputStylesDirs: string[]\n /** Paths to MCP server configuration files */\n mcpConfigFiles: string[]\n /** Paths to LSP server configuration files (Claude Code CLI specific) */\n lspConfigFiles: string[]\n}\n\n/**\n * Plugin scope - where the plugin is installed/activated\n */\nexport type PluginScope = 'user' | 'project' | 'local'\n\n/**\n * Installed skill plugin record\n */\nexport interface InstalledSkillPlugin {\n plugin: string\n marketplace: string\n scope: PluginScope\n kind?: 'skill-pack' | 'plugin-pack'\n isEnabled?: boolean\n projectPath?: string\n installedAt: string\n pluginRoot?: string\n skills: string[]\n commands: string[]\n sourceMarketplacePath: string\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["PluginErrorCode"]
7
7
  }
@@ -77,10 +77,7 @@ async function executeAgentHooks(event, agentConfig, context) {
77
77
  break;
78
78
  }
79
79
  if (!result.success && result.error) {
80
- console.warn(
81
- `Hook ${event} execution failed:`,
82
- result.error.message
83
- );
80
+ console.warn(`Hook ${event} execution failed:`, result.error.message);
84
81
  }
85
82
  }
86
83
  return {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/agentHookExecutor.ts"],
4
- "sourcesContent": ["/**\n * Agent Hook Executor\n *\n * Executes lifecycle hooks for agents as defined in Claude Code specification.\n * Supports onStart, onComplete, and onError hooks with security controls.\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport type { HookDefinition } from '@minto-types/hooks'\nimport type { AgentConfig, AgentHooks } from './agentLoader'\nimport { getCwd } from './state'\n\nconst execAsync = promisify(exec)\n\n/**\n * Hook execution context\n */\nexport interface HookExecutionContext {\n sessionId: string\n agentId: string\n agentType: string\n cwd: string\n env?: Record<string, string>\n error?: Error // For onError hooks\n result?: string // For onComplete hooks\n}\n\n/**\n * Hook execution result\n */\nexport interface HookExecutionResult {\n success: boolean\n continue: boolean\n reason?: string\n output?: string\n error?: Error\n executionTime: number\n}\n\n/**\n * Default hook timeout in milliseconds\n */\nconst DEFAULT_HOOK_TIMEOUT = 60000 // 60 seconds\n\n/**\n * Execute a single hook\n */\nasync function executeHook(\n hook: HookDefinition,\n context: HookExecutionContext,\n): Promise<HookExecutionResult> {\n const startTime = Date.now()\n const timeout = (hook.timeout ?? 60) * 1000 // Convert seconds to milliseconds\n\n try {\n if (hook.type === 'command' && hook.command) {\n // Execute shell command\n const { stdout, stderr } = await execAsync(hook.command, {\n timeout: Math.min(timeout, DEFAULT_HOOK_TIMEOUT),\n cwd: context.cwd,\n env: {\n ...process.env,\n ...context.env,\n AGENT_ID: context.agentId,\n AGENT_TYPE: context.agentType,\n SESSION_ID: context.sessionId,\n HOOK_CWD: context.cwd,\n },\n })\n\n // Try to parse JSON output for hook control\n let parsedOutput: any = null\n try {\n if (stdout.trim().startsWith('{')) {\n parsedOutput = JSON.parse(stdout.trim())\n }\n } catch {\n // Not JSON, that's fine\n }\n\n return {\n success: true,\n continue: parsedOutput?.continue !== false,\n reason: parsedOutput?.stopReason,\n output: stdout,\n executionTime: Date.now() - startTime,\n }\n } else if (hook.type === 'prompt' && hook.prompt) {\n // Prompt hooks are handled by the agent system\n // For now, we just return success and let the caller handle the prompt\n return {\n success: true,\n continue: true,\n output: hook.prompt,\n executionTime: Date.now() - startTime,\n }\n }\n\n // Invalid hook configuration\n return {\n success: false,\n continue: true,\n reason: 'Invalid hook configuration: missing command or prompt',\n executionTime: Date.now() - startTime,\n }\n } catch (error) {\n return {\n success: false,\n continue: true, // Default to continue on error\n error: error instanceof Error ? error : new Error(String(error)),\n executionTime: Date.now() - startTime,\n }\n }\n}\n\n/**\n * Execute agent lifecycle hooks\n *\n * @param event - The lifecycle event (onStart, onComplete, onError)\n * @param agentConfig - The agent configuration containing hooks\n * @param context - The execution context\n * @returns Combined result of all hook executions\n */\nexport async function executeAgentHooks(\n event: keyof AgentHooks,\n agentConfig: AgentConfig,\n context: HookExecutionContext,\n): Promise<{ continue: boolean; reason?: string; outputs: string[] }> {\n const hooks = agentConfig.hooks?.[event]\n\n if (!hooks || hooks.length === 0) {\n return { continue: true, outputs: [] }\n }\n\n const outputs: string[] = []\n let shouldContinue = true\n let stopReason: string | undefined\n\n for (const hook of hooks) {\n const result = await executeHook(hook, context)\n\n if (result.output) {\n outputs.push(result.output)\n }\n\n if (!result.continue) {\n shouldContinue = false\n stopReason = result.reason || 'Hook requested stop'\n break // Stop executing further hooks\n }\n\n if (!result.success && result.error) {\n console.warn(\n `Hook ${event} execution failed:`,\n result.error.message,\n )\n // Continue to next hook on error by default\n }\n }\n\n return {\n continue: shouldContinue,\n reason: stopReason,\n outputs,\n }\n}\n\n/**\n * Create hook execution context from agent execution state\n */\nexport function createHookContext(params: {\n sessionId: string\n agentId: string\n agentType: string\n error?: Error\n result?: string\n}): HookExecutionContext {\n return {\n sessionId: params.sessionId,\n agentId: params.agentId,\n agentType: params.agentType,\n cwd: getCwd(),\n error: params.error,\n result: params.result,\n }\n}\n"],
5
- "mappings": "AAOA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAG1B,SAAS,cAAc;AAEvB,MAAM,YAAY,UAAU,IAAI;AA8BhC,MAAM,uBAAuB;AAK7B,eAAe,YACb,MACA,SAC8B;AAC9B,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,WAAW,KAAK,WAAW,MAAM;AAEvC,MAAI;AACF,QAAI,KAAK,SAAS,aAAa,KAAK,SAAS;AAE3C,YAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU,KAAK,SAAS;AAAA,QACvD,SAAS,KAAK,IAAI,SAAS,oBAAoB;AAAA,QAC/C,KAAK,QAAQ;AAAA,QACb,KAAK;AAAA,UACH,GAAG,QAAQ;AAAA,UACX,GAAG,QAAQ;AAAA,UACX,UAAU,QAAQ;AAAA,UAClB,YAAY,QAAQ;AAAA,UACpB,YAAY,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,QACpB;AAAA,MACF,CAAC;AAGD,UAAI,eAAoB;AACxB,UAAI;AACF,YAAI,OAAO,KAAK,EAAE,WAAW,GAAG,GAAG;AACjC,yBAAe,KAAK,MAAM,OAAO,KAAK,CAAC;AAAA,QACzC;AAAA,MACF,QAAQ;AAAA,MAER;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU,cAAc,aAAa;AAAA,QACrC,QAAQ,cAAc;AAAA,QACtB,QAAQ;AAAA,QACR,eAAe,KAAK,IAAI,IAAI;AAAA,MAC9B;AAAA,IACF,WAAW,KAAK,SAAS,YAAY,KAAK,QAAQ;AAGhD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,KAAK;AAAA,QACb,eAAe,KAAK,IAAI,IAAI;AAAA,MAC9B;AAAA,IACF;AAGA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAe,KAAK,IAAI,IAAI;AAAA,IAC9B;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA;AAAA,MACV,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC/D,eAAe,KAAK,IAAI,IAAI;AAAA,IAC9B;AAAA,EACF;AACF;AAUA,eAAsB,kBACpB,OACA,aACA,SACoE;AACpE,QAAM,QAAQ,YAAY,QAAQ,KAAK;AAEvC,MAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,WAAO,EAAE,UAAU,MAAM,SAAS,CAAC,EAAE;AAAA,EACvC;AAEA,QAAM,UAAoB,CAAC;AAC3B,MAAI,iBAAiB;AACrB,MAAI;AAEJ,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,MAAM,YAAY,MAAM,OAAO;AAE9C,QAAI,OAAO,QAAQ;AACjB,cAAQ,KAAK,OAAO,MAAM;AAAA,IAC5B;AAEA,QAAI,CAAC,OAAO,UAAU;AACpB,uBAAiB;AACjB,mBAAa,OAAO,UAAU;AAC9B;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,WAAW,OAAO,OAAO;AACnC,cAAQ;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,OAAO,MAAM;AAAA,MACf;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AAKO,SAAS,kBAAkB,QAMT;AACvB,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,IAClB,KAAK,OAAO;AAAA,IACZ,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,EACjB;AACF;",
4
+ "sourcesContent": ["/**\n * Agent Hook Executor\n *\n * Executes lifecycle hooks for agents as defined in Claude Code specification.\n * Supports onStart, onComplete, and onError hooks with security controls.\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport type { HookDefinition } from '@minto-types/hooks'\nimport type { AgentConfig, AgentHooks } from './agentLoader'\nimport { getCwd } from './state'\n\nconst execAsync = promisify(exec)\n\n/**\n * Hook execution context\n */\nexport interface HookExecutionContext {\n sessionId: string\n agentId: string\n agentType: string\n cwd: string\n env?: Record<string, string>\n error?: Error // For onError hooks\n result?: string // For onComplete hooks\n}\n\n/**\n * Hook execution result\n */\nexport interface HookExecutionResult {\n success: boolean\n continue: boolean\n reason?: string\n output?: string\n error?: Error\n executionTime: number\n}\n\n/**\n * Default hook timeout in milliseconds\n */\nconst DEFAULT_HOOK_TIMEOUT = 60000 // 60 seconds\n\n/**\n * Execute a single hook\n */\nasync function executeHook(\n hook: HookDefinition,\n context: HookExecutionContext,\n): Promise<HookExecutionResult> {\n const startTime = Date.now()\n const timeout = (hook.timeout ?? 60) * 1000 // Convert seconds to milliseconds\n\n try {\n if (hook.type === 'command' && hook.command) {\n // Execute shell command\n const { stdout, stderr } = await execAsync(hook.command, {\n timeout: Math.min(timeout, DEFAULT_HOOK_TIMEOUT),\n cwd: context.cwd,\n env: {\n ...process.env,\n ...context.env,\n AGENT_ID: context.agentId,\n AGENT_TYPE: context.agentType,\n SESSION_ID: context.sessionId,\n HOOK_CWD: context.cwd,\n },\n })\n\n // Try to parse JSON output for hook control\n let parsedOutput: any = null\n try {\n if (stdout.trim().startsWith('{')) {\n parsedOutput = JSON.parse(stdout.trim())\n }\n } catch {\n // Not JSON, that's fine\n }\n\n return {\n success: true,\n continue: parsedOutput?.continue !== false,\n reason: parsedOutput?.stopReason,\n output: stdout,\n executionTime: Date.now() - startTime,\n }\n } else if (hook.type === 'prompt' && hook.prompt) {\n // Prompt hooks are handled by the agent system\n // For now, we just return success and let the caller handle the prompt\n return {\n success: true,\n continue: true,\n output: hook.prompt,\n executionTime: Date.now() - startTime,\n }\n }\n\n // Invalid hook configuration\n return {\n success: false,\n continue: true,\n reason: 'Invalid hook configuration: missing command or prompt',\n executionTime: Date.now() - startTime,\n }\n } catch (error) {\n return {\n success: false,\n continue: true, // Default to continue on error\n error: error instanceof Error ? error : new Error(String(error)),\n executionTime: Date.now() - startTime,\n }\n }\n}\n\n/**\n * Execute agent lifecycle hooks\n *\n * @param event - The lifecycle event (onStart, onComplete, onError)\n * @param agentConfig - The agent configuration containing hooks\n * @param context - The execution context\n * @returns Combined result of all hook executions\n */\nexport async function executeAgentHooks(\n event: keyof AgentHooks,\n agentConfig: AgentConfig,\n context: HookExecutionContext,\n): Promise<{ continue: boolean; reason?: string; outputs: string[] }> {\n const hooks = agentConfig.hooks?.[event]\n\n if (!hooks || hooks.length === 0) {\n return { continue: true, outputs: [] }\n }\n\n const outputs: string[] = []\n let shouldContinue = true\n let stopReason: string | undefined\n\n for (const hook of hooks) {\n const result = await executeHook(hook, context)\n\n if (result.output) {\n outputs.push(result.output)\n }\n\n if (!result.continue) {\n shouldContinue = false\n stopReason = result.reason || 'Hook requested stop'\n break // Stop executing further hooks\n }\n\n if (!result.success && result.error) {\n console.warn(`Hook ${event} execution failed:`, result.error.message)\n // Continue to next hook on error by default\n }\n }\n\n return {\n continue: shouldContinue,\n reason: stopReason,\n outputs,\n }\n}\n\n/**\n * Create hook execution context from agent execution state\n */\nexport function createHookContext(params: {\n sessionId: string\n agentId: string\n agentType: string\n error?: Error\n result?: string\n}): HookExecutionContext {\n return {\n sessionId: params.sessionId,\n agentId: params.agentId,\n agentType: params.agentType,\n cwd: getCwd(),\n error: params.error,\n result: params.result,\n }\n}\n"],
5
+ "mappings": "AAOA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAG1B,SAAS,cAAc;AAEvB,MAAM,YAAY,UAAU,IAAI;AA8BhC,MAAM,uBAAuB;AAK7B,eAAe,YACb,MACA,SAC8B;AAC9B,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,WAAW,KAAK,WAAW,MAAM;AAEvC,MAAI;AACF,QAAI,KAAK,SAAS,aAAa,KAAK,SAAS;AAE3C,YAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU,KAAK,SAAS;AAAA,QACvD,SAAS,KAAK,IAAI,SAAS,oBAAoB;AAAA,QAC/C,KAAK,QAAQ;AAAA,QACb,KAAK;AAAA,UACH,GAAG,QAAQ;AAAA,UACX,GAAG,QAAQ;AAAA,UACX,UAAU,QAAQ;AAAA,UAClB,YAAY,QAAQ;AAAA,UACpB,YAAY,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,QACpB;AAAA,MACF,CAAC;AAGD,UAAI,eAAoB;AACxB,UAAI;AACF,YAAI,OAAO,KAAK,EAAE,WAAW,GAAG,GAAG;AACjC,yBAAe,KAAK,MAAM,OAAO,KAAK,CAAC;AAAA,QACzC;AAAA,MACF,QAAQ;AAAA,MAER;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU,cAAc,aAAa;AAAA,QACrC,QAAQ,cAAc;AAAA,QACtB,QAAQ;AAAA,QACR,eAAe,KAAK,IAAI,IAAI;AAAA,MAC9B;AAAA,IACF,WAAW,KAAK,SAAS,YAAY,KAAK,QAAQ;AAGhD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,KAAK;AAAA,QACb,eAAe,KAAK,IAAI,IAAI;AAAA,MAC9B;AAAA,IACF;AAGA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAe,KAAK,IAAI,IAAI;AAAA,IAC9B;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA;AAAA,MACV,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC/D,eAAe,KAAK,IAAI,IAAI;AAAA,IAC9B;AAAA,EACF;AACF;AAUA,eAAsB,kBACpB,OACA,aACA,SACoE;AACpE,QAAM,QAAQ,YAAY,QAAQ,KAAK;AAEvC,MAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,WAAO,EAAE,UAAU,MAAM,SAAS,CAAC,EAAE;AAAA,EACvC;AAEA,QAAM,UAAoB,CAAC;AAC3B,MAAI,iBAAiB;AACrB,MAAI;AAEJ,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,MAAM,YAAY,MAAM,OAAO;AAE9C,QAAI,OAAO,QAAQ;AACjB,cAAQ,KAAK,OAAO,MAAM;AAAA,IAC5B;AAEA,QAAI,CAAC,OAAO,UAAU;AACpB,uBAAiB;AACjB,mBAAa,OAAO,UAAU;AAC9B;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,WAAW,OAAO,OAAO;AACnC,cAAQ,KAAK,QAAQ,KAAK,sBAAsB,OAAO,MAAM,OAAO;AAAA,IAEtE;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AAKO,SAAS,kBAAkB,QAMT;AACvB,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,IAClB,KAAK,OAAO;AAAA,IACZ,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,EACjB;AACF;",
6
6
  "names": []
7
7
  }
@@ -217,12 +217,24 @@ async function scanAgentDirectory(dirPath, location) {
217
217
  if (!stat.isFile()) continue;
218
218
  try {
219
219
  const content = readFileSync(filePath, "utf-8");
220
+ if (!content.trim()) continue;
220
221
  const { data: frontmatter, content: body } = matter(content);
221
222
  if (!frontmatter.name || !frontmatter.description) {
222
- console.warn(
223
- `Skipping ${filePath}: missing required fields (name, description)`
224
- );
225
- continue;
223
+ const headingMatch = body.match(/^#\s+(.+)/m);
224
+ const firstParagraph = body.split(/\n\n/).find((p) => p.trim() && !p.trim().startsWith("#"));
225
+ if (headingMatch) {
226
+ if (!frontmatter.name) {
227
+ frontmatter.name = headingMatch[1].trim();
228
+ }
229
+ if (!frontmatter.description) {
230
+ frontmatter.description = firstParagraph?.trim() || frontmatter.name;
231
+ }
232
+ } else {
233
+ console.warn(
234
+ `Skipping ${filePath}: missing required fields (name, description)`
235
+ );
236
+ continue;
237
+ }
226
238
  }
227
239
  if (frontmatter.model && !frontmatter.model_name && !warnedAgents.has(frontmatter.name) && process.env.MINTO_DEBUG_AGENTS) {
228
240
  console.warn(
@@ -230,7 +242,9 @@ async function scanAgentDirectory(dirPath, location) {
230
242
  );
231
243
  warnedAgents.add(frontmatter.name);
232
244
  }
233
- const disallowedTools = parseDisallowedTools(frontmatter.disallowedTools);
245
+ const disallowedTools = parseDisallowedTools(
246
+ frontmatter.disallowedTools
247
+ );
234
248
  const skills = parseSkills(frontmatter.skills);
235
249
  const memory = parseMemory(frontmatter.memory);
236
250
  const permissionMode = parsePermissionMode(frontmatter.permissionMode);
@@ -240,6 +254,7 @@ async function scanAgentDirectory(dirPath, location) {
240
254
  tools: parseTools(frontmatter.tools),
241
255
  systemPrompt: body.trim(),
242
256
  location,
257
+ sourcePath: filePath,
243
258
  // Optional fields - only include if defined
244
259
  ...frontmatter.color && { color: frontmatter.color },
245
260
  ...frontmatter.model_name && { model_name: frontmatter.model_name },
@@ -271,12 +286,24 @@ async function loadPluginAgents() {
271
286
  for (const pluginAgent of plugin.agents) {
272
287
  try {
273
288
  const content = readFileSync(pluginAgent.filePath, "utf-8");
289
+ if (!content.trim()) continue;
274
290
  const { data: frontmatter, content: body } = matter(content);
275
291
  if (!frontmatter.name || !frontmatter.description) {
276
- console.warn(
277
- `Skipping plugin agent ${pluginAgent.filePath}: missing required fields (name, description)`
278
- );
279
- continue;
292
+ const headingMatch = body.match(/^#\s+(.+)/m);
293
+ const firstParagraph = body.split(/\n\n/).find((p) => p.trim() && !p.trim().startsWith("#"));
294
+ if (headingMatch) {
295
+ if (!frontmatter.name) {
296
+ frontmatter.name = headingMatch[1].trim();
297
+ }
298
+ if (!frontmatter.description) {
299
+ frontmatter.description = firstParagraph?.trim() || frontmatter.name;
300
+ }
301
+ } else {
302
+ console.warn(
303
+ `Skipping plugin agent ${pluginAgent.filePath}: missing required fields (name, description)`
304
+ );
305
+ continue;
306
+ }
280
307
  }
281
308
  if (frontmatter.model && !frontmatter.model_name && !warnedAgents.has(frontmatter.name) && process.env.MINTO_DEBUG_AGENTS) {
282
309
  console.warn(
@@ -284,7 +311,9 @@ async function loadPluginAgents() {
284
311
  );
285
312
  warnedAgents.add(frontmatter.name);
286
313
  }
287
- const disallowedTools = parseDisallowedTools(frontmatter.disallowedTools);
314
+ const disallowedTools = parseDisallowedTools(
315
+ frontmatter.disallowedTools
316
+ );
288
317
  const skills = parseSkills(frontmatter.skills);
289
318
  const memory = parseMemory(frontmatter.memory);
290
319
  const permissionMode = parsePermissionMode(frontmatter.permissionMode);
@@ -295,9 +324,12 @@ async function loadPluginAgents() {
295
324
  systemPrompt: body.trim(),
296
325
  location: "plugin",
297
326
  pluginName: plugin.manifest.name,
327
+ sourcePath: pluginAgent.filePath,
298
328
  // Optional fields
299
329
  ...frontmatter.color && { color: frontmatter.color },
300
- ...frontmatter.model_name && { model_name: frontmatter.model_name },
330
+ ...frontmatter.model_name && {
331
+ model_name: frontmatter.model_name
332
+ },
301
333
  ...disallowedTools && { disallowedTools },
302
334
  ...permissionMode && { permissionMode },
303
335
  ...skills && { skills },
@@ -305,7 +337,9 @@ async function loadPluginAgents() {
305
337
  ...frontmatter.maxThinkingTokens && {
306
338
  maxThinkingTokens: Number(frontmatter.maxThinkingTokens)
307
339
  },
308
- ...frontmatter.hooks && { hooks: frontmatter.hooks }
340
+ ...frontmatter.hooks && {
341
+ hooks: frontmatter.hooks
342
+ }
309
343
  };
310
344
  agents.push(agent);
311
345
  } catch (error) {
@@ -325,11 +359,21 @@ async function loadAllAgents() {
325
359
  try {
326
360
  const home = homedir();
327
361
  const cwd = getCwd();
362
+ const userClaudeDir = join(home, ".claude", "agents");
328
363
  const userMintoDir = join(home, ".minto", "agents");
364
+ const projectClaudeDir = join(cwd, ".claude", "agents");
329
365
  const projectMintoDir = join(cwd, ".minto", "agents");
330
- const [pluginAgents, userMintoAgents, projectMintoAgents] = await Promise.all([
366
+ const [
367
+ pluginAgents,
368
+ userClaudeAgents,
369
+ userMintoAgents,
370
+ projectClaudeAgents,
371
+ projectMintoAgents
372
+ ] = await Promise.all([
331
373
  loadPluginAgents(),
374
+ scanAgentDirectory(userClaudeDir, "user"),
332
375
  scanAgentDirectory(userMintoDir, "user"),
376
+ scanAgentDirectory(projectClaudeDir, "project"),
333
377
  scanAgentDirectory(projectMintoDir, "project")
334
378
  ]);
335
379
  const agentMap = /* @__PURE__ */ new Map();
@@ -339,9 +383,15 @@ async function loadAllAgents() {
339
383
  for (const agent of pluginAgents) {
340
384
  agentMap.set(agent.agentType, agent);
341
385
  }
386
+ for (const agent of userClaudeAgents) {
387
+ agentMap.set(agent.agentType, agent);
388
+ }
342
389
  for (const agent of userMintoAgents) {
343
390
  agentMap.set(agent.agentType, agent);
344
391
  }
392
+ for (const agent of projectClaudeAgents) {
393
+ agentMap.set(agent.agentType, agent);
394
+ }
345
395
  for (const agent of projectMintoAgents) {
346
396
  agentMap.set(agent.agentType, agent);
347
397
  }
@@ -349,7 +399,9 @@ async function loadAllAgents() {
349
399
  const allAgents = [
350
400
  ...BUILTIN_AGENTS,
351
401
  ...pluginAgents,
402
+ ...userClaudeAgents,
352
403
  ...userMintoAgents,
404
+ ...projectClaudeAgents,
353
405
  ...projectMintoAgents
354
406
  ];
355
407
  return { activeAgents, allAgents };
@@ -391,7 +443,9 @@ async function startAgentWatcher(onChange) {
391
443
  const home = homedir();
392
444
  const cwd = getCwd();
393
445
  const directories = [
446
+ { path: join(home, ".claude", "agents"), label: "user/.claude" },
394
447
  { path: join(home, ".minto", "agents"), label: "user/.minto" },
448
+ { path: join(cwd, ".claude", "agents"), label: "project/.claude" },
395
449
  { path: join(cwd, ".minto", "agents"), label: "project/.minto" }
396
450
  ];
397
451
  const watchDirectory = (dirPath, label) => {