@iaforged/context-code 2.1.7 → 2.2.4

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 (411) hide show
  1. package/dist/src/Task.js +1 -1
  2. package/dist/src/commands/login/login.js +1 -1
  3. package/dist/src/components/ConsoleOAuthFlow.js +1 -1
  4. package/dist/src/constants/oauth.js +1 -1
  5. package/dist/src/context/mailbox.js +1 -1
  6. package/dist/src/context/voice.js +1 -1
  7. package/dist/src/hooks/useTerminalSize.js +1 -1
  8. package/dist/src/ink/Ansi.js +1 -1
  9. package/dist/src/ink/clearTerminal.js +1 -1
  10. package/dist/src/ink/colorize.js +1 -1
  11. package/dist/src/ink/components/App.js +1 -1
  12. package/dist/src/ink/components/Button.js +1 -1
  13. package/dist/src/ink/components/ClockContext.js +1 -1
  14. package/dist/src/ink/components/CursorDeclarationContext.js +1 -1
  15. package/dist/src/ink/components/Link.js +1 -1
  16. package/dist/src/ink/components/StdinContext.js +1 -1
  17. package/dist/src/ink/components/TerminalFocusContext.js +1 -1
  18. package/dist/src/ink/dom.js +1 -1
  19. package/dist/src/ink/events/keyboard-event.js +1 -1
  20. package/dist/src/ink/hit-test.js +1 -1
  21. package/dist/src/ink/hooks/use-animation-frame.js +1 -1
  22. package/dist/src/ink/hooks/use-app.js +1 -1
  23. package/dist/src/ink/hooks/use-input.js +1 -1
  24. package/dist/src/ink/hooks/use-interval.js +1 -1
  25. package/dist/src/ink/hooks/use-selection.js +1 -1
  26. package/dist/src/ink/hooks/use-tab-status.js +1 -1
  27. package/dist/src/ink/hooks/use-terminal-focus.js +1 -1
  28. package/dist/src/ink/hooks/use-terminal-title.js +1 -1
  29. package/dist/src/ink/hooks/use-terminal-viewport.js +1 -1
  30. package/dist/src/ink/ink.js +1 -1
  31. package/dist/src/ink/layout/yoga.js +1 -1
  32. package/dist/src/ink/line-width-cache.js +1 -1
  33. package/dist/src/ink/log-update.js +1 -1
  34. package/dist/src/ink/measure-text.js +1 -1
  35. package/dist/src/ink/output.js +1 -1
  36. package/dist/src/ink/parse-keypress.js +1 -1
  37. package/dist/src/ink/reconciler.js +1 -1
  38. package/dist/src/ink/render-border.js +1 -1
  39. package/dist/src/ink/render-node-to-output.js +1 -1
  40. package/dist/src/ink/render-to-screen.js +1 -1
  41. package/dist/src/ink/renderer.js +1 -1
  42. package/dist/src/ink/root.js +1 -1
  43. package/dist/src/ink/screen.js +1 -1
  44. package/dist/src/ink/searchHighlight.js +1 -1
  45. package/dist/src/ink/selection.js +1 -1
  46. package/dist/src/ink/squash-text-nodes.js +1 -1
  47. package/dist/src/ink/stringWidth.js +1 -1
  48. package/dist/src/ink/tabstops.js +1 -1
  49. package/dist/src/ink/terminal.js +1 -1
  50. package/dist/src/ink/termio/osc.js +1 -1
  51. package/dist/src/ink/termio/parser.js +1 -1
  52. package/dist/src/ink/termio/tokenize.js +1 -1
  53. package/dist/src/ink/useTerminalNotification.js +1 -1
  54. package/dist/src/ink/warn.js +1 -1
  55. package/dist/src/ink/widest-line.js +1 -1
  56. package/dist/src/ink/wrap-text.js +1 -1
  57. package/dist/src/ink/wrapAnsi.js +1 -1
  58. package/dist/src/native-ts/yoga-layout/index.js +1 -1
  59. package/dist/src/schemas/hooks.js +1 -1
  60. package/dist/src/services/SessionMemory/sessionMemoryUtils.js +1 -1
  61. package/dist/src/services/api/client.js +1 -1
  62. package/dist/src/services/api/dumpPrompts.js +1 -1
  63. package/dist/src/services/api/errorUtils.js +1 -1
  64. package/dist/src/services/api/promptCacheBreakDetection.js +1 -1
  65. package/dist/src/services/api/withRetry.js +1 -1
  66. package/dist/src/services/autoDream/consolidationLock.js +1 -1
  67. package/dist/src/services/mcp/elicitationHandler.js +1 -1
  68. package/dist/src/services/mcp/mcpStringUtils.js +1 -1
  69. package/dist/src/services/mcp/oauthPort.js +1 -1
  70. package/dist/src/services/mcp/vscodeSdkMcp.js +1 -1
  71. package/dist/src/services/oauth/client.js +1 -1
  72. package/dist/src/services/oauth/getOauthProfile.js +1 -1
  73. package/dist/src/services/objetivo/types.js +1 -1
  74. package/dist/src/services/rateLimitMocking.js +1 -1
  75. package/dist/src/services/remoteManagedSettings/syncCacheState.js +1 -1
  76. package/dist/src/skills/bundledSkills.js +1 -1
  77. package/dist/src/tasks/DreamTask/DreamTask.js +1 -1
  78. package/dist/src/tools/AgentTool/agentMemory.js +1 -1
  79. package/dist/src/tools/AgentTool/forkSubagent.js +1 -1
  80. package/dist/src/tools/BashTool/BashToolResultMessage.js +1 -1
  81. package/dist/src/tools/BashTool/UI.js +1 -1
  82. package/dist/src/tools/BashTool/sedEditParser.js +1 -1
  83. package/dist/src/tools/BashTool/utils.js +1 -1
  84. package/dist/src/tools/FileReadTool/imageProcessor.js +1 -1
  85. package/dist/src/tools/FileReadTool/prompt.js +1 -1
  86. package/dist/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.js +1 -1
  87. package/dist/src/tools/ListMcpResourcesTool/UI.js +1 -1
  88. package/dist/src/tools/MCPTool/MCPTool.js +1 -1
  89. package/dist/src/tools/MCPTool/UI.js +1 -1
  90. package/dist/src/tools/McpAuthTool/McpAuthTool.js +1 -1
  91. package/dist/src/tools/NotebookEditTool/prompt.js +1 -1
  92. package/dist/src/tools/PowerShellTool/PowerShellTool.js +1 -1
  93. package/dist/src/tools/PowerShellTool/UI.js +1 -1
  94. package/dist/src/tools/PowerShellTool/gitSafety.js +1 -1
  95. package/dist/src/tools/PowerShellTool/modeValidation.js +1 -1
  96. package/dist/src/tools/PowerShellTool/pathValidation.js +1 -1
  97. package/dist/src/tools/PowerShellTool/powershellPermissions.js +1 -1
  98. package/dist/src/tools/PowerShellTool/powershellSecurity.js +1 -1
  99. package/dist/src/tools/PowerShellTool/prompt.js +1 -1
  100. package/dist/src/tools/PowerShellTool/readOnlyValidation.js +1 -1
  101. package/dist/src/tools/REPLTool/constants.js +1 -1
  102. package/dist/src/tools/REPLTool/primitiveTools.js +1 -1
  103. package/dist/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.js +1 -1
  104. package/dist/src/tools/ReadMcpResourceTool/UI.js +1 -1
  105. package/dist/src/tools/ScheduleCronTool/prompt.js +1 -1
  106. package/dist/src/tools/SkillTool/prompt.js +1 -1
  107. package/dist/src/tools/TodoWriteTool/TodoWriteTool.js +1 -1
  108. package/dist/src/tools/ToolSearchTool/prompt.js +1 -1
  109. package/dist/src/tools/WebSearchTool/prompt.js +1 -1
  110. package/dist/src/tools/shared/gitOperationTracking.js +1 -1
  111. package/dist/src/types/permissions.js +1 -1
  112. package/dist/src/utils/Cursor.js +1 -1
  113. package/dist/src/utils/QueryGuard.js +1 -1
  114. package/dist/src/utils/Shell.js +1 -1
  115. package/dist/src/utils/ShellCommand.js +1 -1
  116. package/dist/src/utils/activityManager.js +1 -1
  117. package/dist/src/utils/advisor.js +1 -1
  118. package/dist/src/utils/appleTerminalBackup.js +1 -1
  119. package/dist/src/utils/argumentSubstitution.js +1 -1
  120. package/dist/src/utils/authFileDescriptor.js +1 -1
  121. package/dist/src/utils/autoUpdater.js +1 -1
  122. package/dist/src/utils/background/remote/preconditions.js +1 -1
  123. package/dist/src/utils/background/remote/remoteSession.js +1 -1
  124. package/dist/src/utils/bash/ShellSnapshot.js +1 -1
  125. package/dist/src/utils/bash/ast.js +1 -1
  126. package/dist/src/utils/bash/bashParser.js +1 -1
  127. package/dist/src/utils/bash/bashPipeCommand.js +1 -1
  128. package/dist/src/utils/bash/parser.js +1 -1
  129. package/dist/src/utils/bash/shellQuote.js +1 -1
  130. package/dist/src/utils/bash/shellQuoting.js +1 -1
  131. package/dist/src/utils/billing.js +1 -1
  132. package/dist/src/utils/caCerts.js +1 -1
  133. package/dist/src/utils/claudeInChrome/common.js +1 -1
  134. package/dist/src/utils/claudeInChrome/setupPortable.js +1 -1
  135. package/dist/src/utils/claudemd.js +1 -1
  136. package/dist/src/utils/collapseBackgroundBashNotifications.js +1 -1
  137. package/dist/src/utils/collapseReadSearch.js +1 -1
  138. package/dist/src/utils/completionCache.js +1 -1
  139. package/dist/src/utils/computerUse/common.js +1 -1
  140. package/dist/src/utils/concurrentSessions.js +1 -1
  141. package/dist/src/utils/context.js +1 -1
  142. package/dist/src/utils/cron.js +1 -1
  143. package/dist/src/utils/cronTasks.js +1 -1
  144. package/dist/src/utils/cwd.js +1 -1
  145. package/dist/src/utils/debug.js +1 -1
  146. package/dist/src/utils/debugFilter.js +1 -1
  147. package/dist/src/utils/detectRepository.js +1 -1
  148. package/dist/src/utils/diagLogs.js +1 -1
  149. package/dist/src/utils/diff.js +1 -1
  150. package/dist/src/utils/directMemberMessage.js +1 -1
  151. package/dist/src/utils/doctorDiagnostic.js +1 -1
  152. package/dist/src/utils/dxt/helpers.js +1 -1
  153. package/dist/src/utils/dxt/zip.js +1 -1
  154. package/dist/src/utils/earlyInput.js +1 -1
  155. package/dist/src/utils/editor.js +1 -1
  156. package/dist/src/utils/effort.js +1 -1
  157. package/dist/src/utils/embeddedTools.js +1 -1
  158. package/dist/src/utils/envDynamic.js +1 -1
  159. package/dist/src/utils/envUtils.js +1 -1
  160. package/dist/src/utils/execFileNoThrowPortable.js +1 -1
  161. package/dist/src/utils/execSyncWrapper.js +1 -1
  162. package/dist/src/utils/exportRenderer.js +1 -1
  163. package/dist/src/utils/extraUsage.js +1 -1
  164. package/dist/src/utils/fastMode.js +1 -1
  165. package/dist/src/utils/fileOperationAnalytics.js +1 -1
  166. package/dist/src/utils/fileRead.js +1 -1
  167. package/dist/src/utils/findExecutable.js +1 -1
  168. package/dist/src/utils/format.js +1 -1
  169. package/dist/src/utils/frontmatterParser.js +1 -1
  170. package/dist/src/utils/fsOperations.js +1 -1
  171. package/dist/src/utils/fullscreen.js +1 -1
  172. package/dist/src/utils/genericProcessUtils.js +1 -1
  173. package/dist/src/utils/getWorktreePaths.js +1 -1
  174. package/dist/src/utils/git/gitConfigParser.js +1 -1
  175. package/dist/src/utils/git/gitFilesystem.js +1 -1
  176. package/dist/src/utils/git/gitignore.js +1 -1
  177. package/dist/src/utils/gitDiff.js +1 -1
  178. package/dist/src/utils/gitSettings.js +1 -1
  179. package/dist/src/utils/glob.js +1 -1
  180. package/dist/src/utils/gracefulShutdown.js +1 -1
  181. package/dist/src/utils/groupToolUses.js +1 -1
  182. package/dist/src/utils/handlePromptSubmit.js +1 -1
  183. package/dist/src/utils/hash.js +1 -1
  184. package/dist/src/utils/hooks/fileChangedWatcher.js +1 -1
  185. package/dist/src/utils/hooks/hooksSettings.js +1 -1
  186. package/dist/src/utils/hooks/registerSkillHooks.js +1 -1
  187. package/dist/src/utils/hooks/sessionHooks.js +1 -1
  188. package/dist/src/utils/http.js +1 -1
  189. package/dist/src/utils/hyperlink.js +1 -1
  190. package/dist/src/utils/ide.js +1 -1
  191. package/dist/src/utils/idePathConversion.js +1 -1
  192. package/dist/src/utils/imagePaste.js +1 -1
  193. package/dist/src/utils/imageResizer.js +1 -1
  194. package/dist/src/utils/imageStore.js +1 -1
  195. package/dist/src/utils/inProcessTeammateHelpers.js +1 -1
  196. package/dist/src/utils/ink.js +1 -1
  197. package/dist/src/utils/jetbrains.js +1 -1
  198. package/dist/src/utils/json.js +1 -1
  199. package/dist/src/utils/listSessionsImpl.js +1 -1
  200. package/dist/src/utils/localInstaller.js +1 -1
  201. package/dist/src/utils/lockfile.js +1 -1
  202. package/dist/src/utils/logoV2Utils.js +1 -1
  203. package/dist/src/utils/markdown.js +1 -1
  204. package/dist/src/utils/mcp/dateTimeParser.js +1 -1
  205. package/dist/src/utils/mcpOutputStorage.js +1 -1
  206. package/dist/src/utils/mcpValidation.js +1 -1
  207. package/dist/src/utils/memoize.js +1 -1
  208. package/dist/src/utils/memory/types.js +1 -1
  209. package/dist/src/utils/memoryFileDetection.js +1 -1
  210. package/dist/src/utils/messageQueueManager.js +1 -1
  211. package/dist/src/utils/messages/mappers.js +1 -1
  212. package/dist/src/utils/messages/systemInit.js +1 -1
  213. package/dist/src/utils/model/antModels.js +1 -1
  214. package/dist/src/utils/model/check1mAccess.js +1 -1
  215. package/dist/src/utils/model/contextWindowUpgradeCheck.js +1 -1
  216. package/dist/src/utils/model/model.js +1 -1
  217. package/dist/src/utils/model/modelAllowlist.js +1 -1
  218. package/dist/src/utils/model/modelCapabilities.js +1 -1
  219. package/dist/src/utils/model/modelOptions.js +1 -1
  220. package/dist/src/utils/model/modelStrings.js +1 -1
  221. package/dist/src/utils/model/providerBaseUrls.js +1 -1
  222. package/dist/src/utils/model/providerCatalog.js +1 -1
  223. package/dist/src/utils/model/providerModels.js +1 -1
  224. package/dist/src/utils/model/providerProfiles.js +1 -1
  225. package/dist/src/utils/model/providerProfilesDb.js +1 -1
  226. package/dist/src/utils/model/providerSwitch.js +1 -1
  227. package/dist/src/utils/model/providers.js +1 -1
  228. package/dist/src/utils/modelCost.js +1 -1
  229. package/dist/src/utils/modifiers.js +1 -1
  230. package/dist/src/utils/mtls.js +1 -1
  231. package/dist/src/utils/nativeInstaller/download.js +1 -1
  232. package/dist/src/utils/nativeInstaller/installer.js +1 -1
  233. package/dist/src/utils/nativeInstaller/packageManagers.js +1 -1
  234. package/dist/src/utils/nativeInstaller/pidLock.js +1 -1
  235. package/dist/src/utils/notebook.js +1 -1
  236. package/dist/src/utils/pasteStore.js +1 -1
  237. package/dist/src/utils/path.js +1 -1
  238. package/dist/src/utils/permissions/PermissionMode.js +1 -1
  239. package/dist/src/utils/permissions/PermissionPromptToolResultSchema.js +1 -1
  240. package/dist/src/utils/permissions/PermissionUpdate.js +1 -1
  241. package/dist/src/utils/permissions/PermissionUpdateSchema.js +1 -1
  242. package/dist/src/utils/permissions/autoModeState.js +1 -1
  243. package/dist/src/utils/permissions/bypassPermissionsKillswitch.js +1 -1
  244. package/dist/src/utils/permissions/filesystem.js +1 -1
  245. package/dist/src/utils/permissions/getNextPermissionMode.js +1 -1
  246. package/dist/src/utils/permissions/pathValidation.js +1 -1
  247. package/dist/src/utils/permissions/permissionRuleParser.js +1 -1
  248. package/dist/src/utils/permissions/permissionsDb.js +1 -1
  249. package/dist/src/utils/permissions/permissionsLoader.js +1 -1
  250. package/dist/src/utils/permissions/shellRuleMatching.js +1 -1
  251. package/dist/src/utils/planModeV2.js +1 -1
  252. package/dist/src/utils/plans.js +1 -1
  253. package/dist/src/utils/platform.js +1 -1
  254. package/dist/src/utils/plugins/addDirPluginSettings.js +1 -1
  255. package/dist/src/utils/plugins/cacheUtils.js +1 -1
  256. package/dist/src/utils/plugins/dependencyResolver.js +1 -1
  257. package/dist/src/utils/plugins/fetchTelemetry.js +1 -1
  258. package/dist/src/utils/plugins/gitAvailability.js +1 -1
  259. package/dist/src/utils/plugins/hintRecommendation.js +1 -1
  260. package/dist/src/utils/plugins/installedPluginsManager.js +1 -1
  261. package/dist/src/utils/plugins/loadPluginAgents.js +1 -1
  262. package/dist/src/utils/plugins/loadPluginCommands.js +1 -1
  263. package/dist/src/utils/plugins/loadPluginHooks.js +1 -1
  264. package/dist/src/utils/plugins/loadPluginOutputStyles.js +1 -1
  265. package/dist/src/utils/plugins/lspPluginIntegration.js +1 -1
  266. package/dist/src/utils/plugins/lspRecommendation.js +1 -1
  267. package/dist/src/utils/plugins/managedPlugins.js +1 -1
  268. package/dist/src/utils/plugins/marketplaceHelpers.js +1 -1
  269. package/dist/src/utils/plugins/marketplaceManager.js +1 -1
  270. package/dist/src/utils/plugins/mcpPluginIntegration.js +1 -1
  271. package/dist/src/utils/plugins/mcpbHandler.js +1 -1
  272. package/dist/src/utils/plugins/officialMarketplaceGcs.js +1 -1
  273. package/dist/src/utils/plugins/officialMarketplaceStartupCheck.js +1 -1
  274. package/dist/src/utils/plugins/orphanedPluginFilter.js +1 -1
  275. package/dist/src/utils/plugins/performStartupChecks.js +1 -1
  276. package/dist/src/utils/plugins/pluginAutoupdate.js +1 -1
  277. package/dist/src/utils/plugins/pluginBlocklist.js +1 -1
  278. package/dist/src/utils/plugins/pluginDirectories.js +1 -1
  279. package/dist/src/utils/plugins/pluginFlagging.js +1 -1
  280. package/dist/src/utils/plugins/pluginInstallationHelpers.js +1 -1
  281. package/dist/src/utils/plugins/pluginLoader.js +1 -1
  282. package/dist/src/utils/plugins/pluginOptionsStorage.js +1 -1
  283. package/dist/src/utils/plugins/pluginPolicy.js +1 -1
  284. package/dist/src/utils/plugins/pluginStartupCheck.js +1 -1
  285. package/dist/src/utils/plugins/pluginVersioning.js +1 -1
  286. package/dist/src/utils/plugins/reconciler.js +1 -1
  287. package/dist/src/utils/plugins/refresh.js +1 -1
  288. package/dist/src/utils/plugins/schemas.js +1 -1
  289. package/dist/src/utils/plugins/walkPluginMarkdown.js +1 -1
  290. package/dist/src/utils/plugins/zipCache.js +1 -1
  291. package/dist/src/utils/powershell/parser.js +1 -1
  292. package/dist/src/utils/processUserInput/processBashCommand.js +1 -1
  293. package/dist/src/utils/processUserInput/processSlashCommand.js +1 -1
  294. package/dist/src/utils/processUserInput/processTextPrompt.js +1 -1
  295. package/dist/src/utils/processUserInput/processUserInput.js +1 -1
  296. package/dist/src/utils/profilerBase.js +1 -1
  297. package/dist/src/utils/promptCategory.js +1 -1
  298. package/dist/src/utils/promptEditor.js +1 -1
  299. package/dist/src/utils/promptShellExecution.js +1 -1
  300. package/dist/src/utils/proxy.js +1 -1
  301. package/dist/src/utils/queryHelpers.js +1 -1
  302. package/dist/src/utils/queryProfiler.js +1 -1
  303. package/dist/src/utils/queueProcessor.js +1 -1
  304. package/dist/src/utils/readFileInRange.js +1 -1
  305. package/dist/src/utils/releaseNotes.js +1 -1
  306. package/dist/src/utils/renderOptions.js +1 -1
  307. package/dist/src/utils/ripgrep.js +1 -1
  308. package/dist/src/utils/sandbox/sandbox-adapter.js +1 -1
  309. package/dist/src/utils/sdkEventQueue.js +1 -1
  310. package/dist/src/utils/secureStorage/index.js +1 -1
  311. package/dist/src/utils/secureStorage/macOsKeychainHelpers.js +1 -1
  312. package/dist/src/utils/secureStorage/macOsKeychainStorage.js +1 -1
  313. package/dist/src/utils/secureStorage/plainTextStorage.js +1 -1
  314. package/dist/src/utils/secureStorage/sqliteStorage.js +1 -1
  315. package/dist/src/utils/sessionEnvironment.js +1 -1
  316. package/dist/src/utils/sessionIngressAuth.js +1 -1
  317. package/dist/src/utils/sessionRestore.js +1 -1
  318. package/dist/src/utils/sessionStart.js +1 -1
  319. package/dist/src/utils/sessionTitle.js +1 -1
  320. package/dist/src/utils/settings/managedPath.js +1 -1
  321. package/dist/src/utils/settings/mdm/rawRead.js +1 -1
  322. package/dist/src/utils/settings/mdm/settings.js +1 -1
  323. package/dist/src/utils/settings/permissionValidation.js +1 -1
  324. package/dist/src/utils/settings/pluginOnlyPolicy.js +1 -1
  325. package/dist/src/utils/settings/schemaOutput.js +1 -1
  326. package/dist/src/utils/settings/settings.js +1 -1
  327. package/dist/src/utils/settings/types.js +1 -1
  328. package/dist/src/utils/settings/validateEditTool.js +1 -1
  329. package/dist/src/utils/settings/validation.js +1 -1
  330. package/dist/src/utils/shell/bashProvider.js +1 -1
  331. package/dist/src/utils/shell/powershellDetection.js +1 -1
  332. package/dist/src/utils/shell/powershellProvider.js +1 -1
  333. package/dist/src/utils/shell/readOnlyCommandValidation.js +1 -1
  334. package/dist/src/utils/shell/resolveDefaultShell.js +1 -1
  335. package/dist/src/utils/shell/shellToolUtils.js +1 -1
  336. package/dist/src/utils/shell/specPrefix.js +1 -1
  337. package/dist/src/utils/shellConfig.js +1 -1
  338. package/dist/src/utils/sideQuestion.js +1 -1
  339. package/dist/src/utils/skills/skillChangeDetector.js +1 -1
  340. package/dist/src/utils/slashCommandParsing.js +1 -1
  341. package/dist/src/utils/sliceAnsi.js +1 -1
  342. package/dist/src/utils/slowOperations.js +1 -1
  343. package/dist/src/utils/standaloneAgent.js +1 -1
  344. package/dist/src/utils/startupProfiler.js +1 -1
  345. package/dist/src/utils/staticRender.js +1 -1
  346. package/dist/src/utils/status.js +1 -1
  347. package/dist/src/utils/statusNoticeDefinitions.js +1 -1
  348. package/dist/src/utils/suggestions/commandSuggestions.js +1 -1
  349. package/dist/src/utils/suggestions/directoryCompletion.js +1 -1
  350. package/dist/src/utils/suggestions/shellHistoryCompletion.js +1 -1
  351. package/dist/src/utils/suggestions/skillUsageTracking.js +1 -1
  352. package/dist/src/utils/suggestions/slackChannelSuggestions.js +1 -1
  353. package/dist/src/utils/swarm/backends/detection.js +1 -1
  354. package/dist/src/utils/swarm/permissionSync.js +1 -1
  355. package/dist/src/utils/swarm/reconnection.js +1 -1
  356. package/dist/src/utils/swarm/spawnUtils.js +1 -91
  357. package/dist/src/utils/swarm/teammateInit.js +1 -1
  358. package/dist/src/utils/systemDirectories.js +1 -1
  359. package/dist/src/utils/systemPrompt.js +1 -1
  360. package/dist/src/utils/systemTheme.js +1 -1
  361. package/dist/src/utils/task/TaskOutput.js +1 -1
  362. package/dist/src/utils/task/diskOutput.js +1 -1
  363. package/dist/src/utils/tasks.js +1 -1
  364. package/dist/src/utils/teamDiscovery.js +1 -1
  365. package/dist/src/utils/teamMemoryOps.js +1 -1
  366. package/dist/src/utils/teammateMailbox.js +1 -1
  367. package/dist/src/utils/telemetry/betaSessionTracing.js +1 -1
  368. package/dist/src/utils/telemetry/bigqueryExporter.js +1 -1
  369. package/dist/src/utils/telemetry/events.js +1 -1
  370. package/dist/src/utils/telemetry/instrumentation.js +1 -1
  371. package/dist/src/utils/telemetry/logger.js +1 -1
  372. package/dist/src/utils/telemetry/perfettoTracing.js +1 -1
  373. package/dist/src/utils/telemetry/pluginTelemetry.js +1 -1
  374. package/dist/src/utils/telemetry/sessionTracing.js +1 -1
  375. package/dist/src/utils/telemetryAttributes.js +1 -1
  376. package/dist/src/utils/teleport/api.js +1 -1
  377. package/dist/src/utils/teleport/environments.js +1 -1
  378. package/dist/src/utils/teleport/gitBundle.js +1 -1
  379. package/dist/src/utils/teleport.js +1 -1
  380. package/dist/src/utils/tempfile.js +1 -1
  381. package/dist/src/utils/terminal.js +1 -1
  382. package/dist/src/utils/terminalPanel.js +1 -1
  383. package/dist/src/utils/textHighlighting.js +1 -1
  384. package/dist/src/utils/theme.js +1 -1
  385. package/dist/src/utils/themes/bootstrap.js +1 -1
  386. package/dist/src/utils/themes/loader.js +1 -1
  387. package/dist/src/utils/thinking.js +1 -1
  388. package/dist/src/utils/tmuxSocket.js +1 -1
  389. package/dist/src/utils/tokens.js +1 -1
  390. package/dist/src/utils/toolPool.js +1 -1
  391. package/dist/src/utils/toolResultStorage.js +1 -1
  392. package/dist/src/utils/transcriptSearch.js +1 -1
  393. package/dist/src/utils/truncate.js +1 -1
  394. package/dist/src/utils/ultraplan/keyword.js +1 -1
  395. package/dist/src/utils/unaryLogging.js +1 -1
  396. package/dist/src/utils/undercover.js +1 -1
  397. package/dist/src/utils/user.js +1 -1
  398. package/dist/src/utils/userPromptKeywords.js +1 -1
  399. package/dist/src/utils/which.js +1 -1
  400. package/dist/src/utils/windowsPaths.js +1 -1
  401. package/dist/src/utils/worktree.js +1 -1
  402. package/dist/src/utils/zodToJsonSchema.js +1 -1
  403. package/dist/src/vim/operators.js +1 -1
  404. package/dist/src/vim/textObjects.js +1 -1
  405. package/dist/src/vim/transitions.js +1 -1
  406. package/dist/src/voice/voiceModeEnabled.js +1 -1
  407. package/dist/src/webapp/auth.js +1 -1
  408. package/dist/src/webapp/tunnel.js +1 -1
  409. package/dist/src/whatsapp/bridge.js +1 -1
  410. package/dist/src/whatsapp/mirror.js +1 -1
  411. package/package.json +41 -3
@@ -1 +1 @@
1
- import{z as e}from"zod/v4";import{HooksSchema as t}from"../../schemas/hooks.js";import{McpServerConfigSchema as i}from"../../services/mcp/types.js";import{lazySchema as o}from"../lazySchema.js";export const ALLOWED_OFFICIAL_MARKETPLACE_NAMES=new Set(["claude-code-marketplace","claude-code-plugins","claude-plugins-official","anthropic-marketplace","anthropic-plugins","agent-skills","life-sciences","knowledge-work-plugins"]);const a=new Set(["knowledge-work-plugins"]);export function isMarketplaceAutoUpdate(e,t){const i=e.toLowerCase();return t.autoUpdate??(ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(i)&&!a.has(i))}export const BLOCKED_OFFICIAL_NAME_PATTERN=/(?:official[^a-z0-9]*(contextcompany|claude)|(?:contextcompany|claude)[^a-z0-9]*official|^(?:contextcompany|claude)[^a-z0-9]*(marketplace|plugins|official))/i;const r=/[^\u0020-\u007E]/;export function isBlockedOfficialName(e){return!ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(e.toLowerCase())&&(!!r.test(e)||BLOCKED_OFFICIAL_NAME_PATTERN.test(e))}export const OFFICIAL_GITHUB_ORG="anthropics";export function validateOfficialNameSource(e,t){const i=e.toLowerCase();if(!ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(i))return null;if("github"===t.source)return(t.repo||"").toLowerCase().startsWith("anthropics/")?null:`The name '${e}' is reserved for official ContextCompany marketplaces. Only repositories from 'github.com/anthropics/' can use this name.`;if("git"===t.source&&t.url){const i=t.url.toLowerCase(),o=i.includes("github.com/anthropics/"),a=i.includes("git@github.com:anthropics/");return o||a?null:`The name '${e}' is reserved for official ContextCompany marketplaces. Only repositories from 'github.com/anthropics/' can use this name.`}return`The name '${e}' is reserved for official ContextCompany marketplaces and can only be used with GitHub sources from the 'anthropics' organization.`}const n=o(()=>e.string().startsWith("./")),s=o(()=>n().endsWith(".json")),c=o(()=>e.union([n().refine(e=>e.endsWith(".mcpb")||e.endsWith(".dxt"),{message:"MCPB file path must end with .mcpb or .dxt"}).describe("Path to MCPB file relative to plugin root"),e.string().url().refine(e=>e.endsWith(".mcpb")||e.endsWith(".dxt"),{message:"MCPB URL must end with .mcpb or .dxt"}).describe("URL to MCPB file")])),l=o(()=>n().endsWith(".md")),d=o(()=>e.union([l(),n()])),p=o(()=>e.string().min(1,"Marketplace must have a name").refine(e=>!e.includes(" "),{message:'Marketplace name cannot contain spaces. Use kebab-case (e.g., "my-marketplace")'}).refine(e=>!e.includes("/")&&!e.includes("\\")&&!e.includes("..")&&"."!==e,{message:'Marketplace name cannot contain path separators (/ or \\), ".." sequences, or be "."'}).refine(e=>!isBlockedOfficialName(e),{message:"Marketplace name impersonates an official ContextCompany/Claude marketplace"}).refine(e=>"inline"!==e.toLowerCase(),{message:'Marketplace name "inline" is reserved for --plugin-dir session plugins'}).refine(e=>"builtin"!==e.toLowerCase(),{message:'Marketplace name "builtin" is reserved for built-in plugins'}));export const PluginAuthorSchema=o(()=>e.object({name:e.string().min(1,"Author name cannot be empty").describe("Display name of the plugin author or organization"),email:e.string().optional().describe("Contact email for support or feedback"),url:e.string().optional().describe("Website, GitHub profile, or organization URL")}));const u=o(()=>e.object({name:e.string().min(1,"Plugin name cannot be empty").refine(e=>!e.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Unique identifier for the plugin, used for namespacing (prefer kebab-case)"),version:e.string().optional().describe("Semantic version (e.g., 1.2.3) following semver.org specification"),description:e.string().optional().describe("Brief, user-facing explanation of what the plugin provides"),author:PluginAuthorSchema().optional().describe("Information about the plugin creator or maintainer"),homepage:e.string().url().optional().describe("Plugin homepage or documentation URL"),repository:e.string().optional().describe("Source code repository URL"),license:e.string().optional().describe("SPDX license identifier (e.g., MIT, Apache-2.0)"),keywords:e.array(e.string()).optional().describe("Tags for plugin discovery and categorization"),dependencies:e.array(DependencyRefSchema()).optional().describe('Plugins that must be enabled for this plugin to function. Bare names (no "@marketplace") are resolved against the declaring plugin\'s own marketplace.')}));export const PluginHooksSchema=o(()=>e.object({description:e.string().optional().describe("Brief, user-facing explanation of what these hooks provide"),hooks:e.lazy(()=>t()).describe("The hooks provided by the plugin, in the same format as the one used for settings")}));const g=o(()=>e.object({hooks:e.union([s().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),e.lazy(()=>t()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)"),e.array(e.union([s().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),e.lazy(()=>t()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)")]))])}));export const CommandMetadataSchema=o(()=>e.object({source:d().optional().describe("Path to command markdown file, relative to plugin root"),content:e.string().optional().describe("Inline markdown content for the command"),description:e.string().optional().describe("Command description override"),argumentHint:e.string().optional().describe('Hint for command arguments (e.g., "[file]")'),model:e.string().optional().describe("Default model for this command"),allowedTools:e.array(e.string()).optional().describe("Tools allowed when command runs")}).refine(e=>e.source&&!e.content||!e.source&&e.content,{message:'Command must have either "source" (file path) or "content" (inline markdown), but not both'}));const m=o(()=>e.object({commands:e.union([d().describe("Path to additional command file or skill directory (in addition to those in the commands/ directory, if it exists), relative to the plugin root"),e.array(d().describe("Path to additional command file or skill directory (in addition to those in the commands/ directory, if it exists), relative to the plugin root")).describe("List of paths to additional command files or skill directories"),e.record(e.string(),CommandMetadataSchema()).describe('Object mapping of command names to their metadata and source files. Command name becomes the slash command name (e.g., "about" → "/plugin:about")')])})),h=o(()=>e.object({agents:e.union([l().describe("Path to additional agent file (in addition to those in the agents/ directory, if it exists), relative to the plugin root"),e.array(l().describe("Path to additional agent file (in addition to those in the agents/ directory, if it exists), relative to the plugin root")).describe("List of paths to additional agent files")])})),b=o(()=>e.object({skills:e.union([n().describe("Path to additional skill directory (in addition to those in the skills/ directory, if it exists), relative to the plugin root"),e.array(n().describe("Path to additional skill directory (in addition to those in the skills/ directory, if it exists), relative to the plugin root")).describe("List of paths to additional skill directories")])})),f=o(()=>e.object({outputStyles:e.union([n().describe("Path to additional output styles directory or file (in addition to those in the output-styles/ directory, if it exists), relative to the plugin root"),e.array(n().describe("Path to additional output styles directory or file (in addition to those in the output-styles/ directory, if it exists), relative to the plugin root")).describe("List of paths to additional output styles directories or files")])})),y=o(()=>e.string().min(1)),k=o(()=>e.string().min(2).refine(e=>e.startsWith("."),{message:'File extensions must start with dot (e.g., ".ts", not "ts")'})),v=o(()=>e.object({mcpServers:e.union([s().describe("MCP servers to include in the plugin (in addition to those in the .mcp.json file, if it exists)"),c().describe("Path or URL to MCPB file containing MCP server configuration"),e.record(e.string(),i()).describe("MCP server configurations keyed by server name"),e.array(e.union([s().describe("Path to MCP servers configuration file"),c().describe("Path or URL to MCPB file"),e.record(e.string(),i()).describe("Inline MCP server configurations")])).describe("Array of MCP server configurations (paths, MCPB files, or inline definitions)")])})),P=o(()=>e.object({type:e.enum(["string","number","boolean","directory","file"]).describe("Type of the configuration value"),title:e.string().describe("Human-readable label shown in the config dialog"),description:e.string().describe("Help text shown beneath the field in the config dialog"),required:e.boolean().optional().describe("If true, validation fails when this field is empty"),default:e.union([e.string(),e.number(),e.boolean(),e.array(e.string())]).optional().describe("Default value used when the user provides nothing"),multiple:e.boolean().optional().describe("For string type: allow an array of strings"),sensitive:e.boolean().optional().describe("If true, masks dialog input and stores value in secure storage (keychain/credentials file) instead of settings.json"),min:e.number().optional().describe("Minimum value (number type only)"),max:e.number().optional().describe("Maximum value (number type only)")}).strict()),S=o(()=>e.object({userConfig:e.record(e.string().regex(/^[A-Za-z_]\w*$/,"Option keys must be valid identifiers (letters, digits, underscore; no leading digit) — they become CLAUDE_PLUGIN_OPTION_<KEY> env vars in hooks"),P()).optional().describe("User-configurable values this plugin needs. Prompted at enable time. Non-sensitive values saved to settings.json; sensitive values to secure storage (macOS keychain or .credentials.json). Available as ${user_config.KEY} in MCP/LSP server config, hook commands, and (non-sensitive only) skill/agent content. Note: sensitive values share a single keychain entry with OAuth tokens — keep secret counts small to stay under the ~2KB stdin-safe limit (see INC-3028).")})),w=o(()=>e.object({channels:e.array(e.object({server:e.string().min(1).describe("Name of the MCP server this channel binds to. Must match a key in this plugin's mcpServers."),displayName:e.string().optional().describe('Human-readable name shown in the config dialog title (e.g., "Telegram"). Defaults to the server name.'),userConfig:e.record(e.string(),P()).optional().describe("Fields to prompt the user for when enabling this plugin in assistant mode. Saved values are substituted into ${user_config.KEY} references in the mcpServers env.")}).strict()).describe("Channels this plugin provides. Each entry declares an MCP server as a message channel and optionally specifies user configuration to prompt for at enable time.")}));export const LspServerConfigSchema=o(()=>e.strictObject({command:e.string().min(1).refine(e=>!(e.includes(" ")&&!e.startsWith("/")),{message:"Command should not contain spaces. Use args array for arguments."}).describe('Command to execute the LSP server (e.g., "typescript-language-server")'),args:e.array(y()).optional().describe("Command-line arguments to pass to the server"),extensionToLanguage:e.record(k(),y()).refine(e=>Object.keys(e).length>0,{message:"extensionToLanguage must have at least one mapping"}).describe("Mapping from file extension to LSP language ID. File extensions and languages are derived from this mapping."),transport:e.enum(["stdio","socket"]).default("stdio").describe("Communication transport mechanism"),env:e.record(e.string(),e.string()).optional().describe("Environment variables to set when starting the server"),initializationOptions:e.unknown().optional().describe("Initialization options passed to the server during initialization"),settings:e.unknown().optional().describe("Settings passed to the server via workspace/didChangeConfiguration"),workspaceFolder:e.string().optional().describe("Workspace folder path to use for the server"),startupTimeout:e.number().int().positive().optional().describe("Maximum time to wait for server startup (milliseconds)"),shutdownTimeout:e.number().int().positive().optional().describe("Maximum time to wait for graceful shutdown (milliseconds)"),restartOnCrash:e.boolean().optional().describe("Whether to restart the server if it crashes"),maxRestarts:e.number().int().nonnegative().optional().describe("Maximum number of restart attempts before giving up")}));const C=o(()=>e.object({lspServers:e.union([s().describe("Path to .lsp.json configuration file relative to plugin root"),e.record(e.string(),LspServerConfigSchema()).describe("LSP server configurations keyed by server name"),e.array(e.union([s().describe("Path to LSP configuration file"),e.record(e.string(),LspServerConfigSchema()).describe("Inline LSP server configurations")])).describe("Array of LSP server configurations (paths or inline definitions)")])})),x=o(()=>e.string().refine(e=>!e.includes("..")&&!e.includes("//"),"Package name cannot contain path traversal patterns").refine(e=>/^@[a-z0-9][a-z0-9-._]*\/[a-z0-9][a-z0-9-._]*$/.test(e)||/^[a-z0-9][a-z0-9-._]*$/.test(e),"Invalid npm package name format")),M=o(()=>e.object({settings:e.record(e.string(),e.unknown()).optional().describe("Settings to merge when plugin is enabled. Only allowlisted keys are kept (currently: agent)")}));export const PluginManifestSchema=o(()=>e.object({...u().shape,...g().partial().shape,...m().partial().shape,...h().partial().shape,...b().partial().shape,...f().partial().shape,...w().partial().shape,...v().partial().shape,...C().partial().shape,...M().partial().shape,...S().partial().shape}));export const MarketplaceSourceSchema=o(()=>e.discriminatedUnion("source",[e.object({source:e.literal("url"),url:e.string().url().describe("Direct URL to marketplace.json file"),headers:e.record(e.string(),e.string()).optional().describe("Custom HTTP headers (e.g., for authentication)")}),e.object({source:e.literal("github"),repo:e.string().describe("GitHub repository in owner/repo format"),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:e.string().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:e.array(e.string()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.')}),e.object({source:e.literal("git"),url:e.string().describe("Full git repository URL"),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:e.string().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:e.array(e.string()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.')}),e.object({source:e.literal("npm"),package:x().describe("NPM package containing marketplace.json")}),e.object({source:e.literal("file"),path:e.string().describe("Local file path to marketplace.json")}),e.object({source:e.literal("directory"),path:e.string().describe("Local directory containing .claude-plugin/marketplace.json")}),e.object({source:e.literal("hostPattern"),hostPattern:e.string().describe('Regex pattern to match the host/domain extracted from any marketplace source type. For github sources, matches against "github.com". For git sources (SSH or HTTPS), extracts the hostname from the URL. Use in strictKnownMarketplaces to allow all marketplaces from a specific host (e.g., "^github\\.mycompany\\.com$").')}),e.object({source:e.literal("pathPattern"),pathPattern:e.string().describe('Regex pattern matched against the .path field of file and directory sources. Use in strictKnownMarketplaces to allow filesystem-based marketplaces alongside hostPattern restrictions for network sources. Use ".*" to allow all filesystem paths, or a narrower pattern (e.g., "^/opt/approved/") to restrict to specific directories.')}),e.object({source:e.literal("settings"),name:p().refine(e=>!ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(e.toLowerCase()),{message:"Reserved official marketplace names cannot be used with settings sources. validateOfficialNameSource only accepts github/git sources from anthropics/* for these names; a settings source would be rejected after loadAndCacheMarketplace has already written to disk with cleanupNeeded=false."}).describe("Marketplace name. Must match the extraKnownMarketplaces key (enforced); the synthetic manifest is written under this name. Same validation as PluginMarketplaceSchema plus reserved-name rejection — validateOfficialNameSource runs after the disk write, too late to clean up."),plugins:e.array(j()).describe("Plugin entries declared inline in settings.json"),owner:PluginAuthorSchema().optional()}).describe("Inline marketplace manifest defined directly in settings.json. The reconciler writes a synthetic marketplace.json to the cache; diffMarketplaces detects edits via isEqual on the stored source (the plugins array is inside this object, so edits surface as sourceChanged).")]));export const gitSha=o(()=>e.string().length(40).regex(/^[a-f0-9]{40}$/,"Must be a full 40-character lowercase git commit SHA"));export const PluginSourceSchema=o(()=>e.union([n().describe("Path to the plugin root, relative to the marketplace root (the directory containing .claude-plugin/, not .claude-plugin/ itself)"),e.object({source:e.literal("npm"),package:x().or(e.string()).describe("Package name (or url, or local path, or anything else that can be passed to `npm` as a package)"),version:e.string().optional().describe("Specific version or version range (e.g., ^1.0.0, ~2.1.0)"),registry:e.string().url().optional().describe("Custom NPM registry URL (defaults to using system default, likely npmjs.org)")}).describe("NPM package as plugin source"),e.object({source:e.literal("pip"),package:e.string().describe("Python package name as it appears on PyPI"),version:e.string().optional().describe("Version specifier (e.g., ==1.0.0, >=2.0.0, <3.0.0)"),registry:e.string().url().optional().describe("Custom PyPI registry URL (defaults to using system default, likely pypi.org)")}).describe("Python package as plugin source"),e.object({source:e.literal("url"),url:e.string().describe("Full git repository URL (https:// or git@)"),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:gitSha().optional().describe("Specific commit SHA to use")}),e.object({source:e.literal("github"),repo:e.string().describe("GitHub repository in owner/repo format"),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:gitSha().optional().describe("Specific commit SHA to use")}),e.object({source:e.literal("git-subdir"),url:e.string().describe("Git repository: GitHub owner/repo shorthand, https://, or git@ URL"),path:e.string().min(1).describe('Subdirectory within the repo containing the plugin (e.g., "tools/claude-plugin"). Cloned sparsely using partial clone (--filter=tree:0) to minimize bandwidth for monorepos.'),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:gitSha().optional().describe("Specific commit SHA to use")}).describe("Plugin located in a subdirectory of a larger repository (monorepo). Only the specified subdirectory is materialized; the rest of the repo is not downloaded.")]));const j=o(()=>e.object({name:e.string().min(1,"Plugin name cannot be empty").refine(e=>!e.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Plugin name as it appears in the target repository"),source:PluginSourceSchema().describe("Where to fetch the plugin from. Must be a remote source — relative paths have no marketplace repository to resolve against."),description:e.string().optional(),version:e.string().optional(),strict:e.boolean().optional()}).refine(e=>"string"!=typeof e.source,{message:'Plugins in a settings-sourced marketplace must use remote sources (github, git-subdir, npm, url, pip). Relative-path sources like "./foo" have no marketplace repository to resolve against.'}));export function isLocalPluginSource(e){return"string"==typeof e&&e.startsWith("./")}export function isLocalMarketplaceSource(e){return"file"===e.source||"directory"===e.source}export const PluginMarketplaceEntrySchema=o(()=>PluginManifestSchema().partial().extend({name:e.string().min(1,"Plugin name cannot be empty").refine(e=>!e.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Unique identifier matching the plugin name"),source:PluginSourceSchema().describe("Where to fetch the plugin from"),category:e.string().optional().describe('Category for organizing plugins (e.g., "productivity", "development")'),tags:e.array(e.string()).optional().describe("Tags for searchability and discovery"),strict:e.boolean().optional().default(!0).describe("Require the plugin manifest to be present in the plugin folder. If false, the marketplace entry provides the manifest.")}));export const PluginMarketplaceSchema=o(()=>e.object({name:p(),owner:PluginAuthorSchema().describe("Marketplace maintainer or curator information"),plugins:e.array(PluginMarketplaceEntrySchema()).describe("Collection of available plugins in this marketplace"),forceRemoveDeletedPlugins:e.boolean().optional().describe("When true, plugins removed from this marketplace will be automatically uninstalled and flagged for users"),metadata:e.object({pluginRoot:e.string().optional().describe("Base path for relative plugin sources"),version:e.string().optional().describe("Marketplace version"),description:e.string().optional().describe("Marketplace description")}).optional().describe("Optional marketplace metadata"),allowCrossMarketplaceDependenciesOn:e.array(e.string()).optional().describe("Marketplace names whose plugins may be auto-installed as dependencies. Only the root marketplace's allowlist applies — no transitive trust.")}));export const PluginIdSchema=o(()=>e.string().regex(/^[a-z0-9][-a-z0-9._]*@[a-z0-9][-a-z0-9._]*$/i,"Plugin ID must be in format: plugin@marketplace"));const L=/^[a-z0-9][-a-z0-9._]*(@[a-z0-9][-a-z0-9._]*)?(@\^[^@]*)?$/i;export const DependencyRefSchema=o(()=>e.union([e.string().regex(L,"Dependency must be a plugin name, optionally qualified with @marketplace").transform(e=>e.replace(/@\^[^@]*$/,"")),e.object({name:e.string().min(1).regex(/^[a-z0-9][-a-z0-9._]*$/i),marketplace:e.string().min(1).regex(/^[a-z0-9][-a-z0-9._]*$/i).optional()}).loose().transform(e=>e.marketplace?`${e.name}@${e.marketplace}`:e.name)]));export const SettingsPluginEntrySchema=o(()=>e.union([PluginIdSchema(),e.object({id:PluginIdSchema().describe('Plugin identifier (e.g., "formatter@tools")'),version:e.string().optional().describe('Version constraint (e.g., "^2.0.0")'),required:e.boolean().optional().describe("If true, cannot be disabled"),config:e.record(e.string(),e.unknown()).optional().describe("Plugin-specific configuration")})]));export const InstalledPluginSchema=o(()=>e.object({version:e.string().describe("Currently installed version"),installedAt:e.string().describe("ISO 8601 timestamp of installation"),lastUpdated:e.string().optional().describe("ISO 8601 timestamp of last update"),installPath:e.string().describe("Absolute path to the installed plugin directory"),gitCommitSha:e.string().optional().describe("Git commit SHA for git-based plugins (for version tracking)")}));export const InstalledPluginsFileSchemaV1=o(()=>e.object({version:e.literal(1).describe("Schema version 1"),plugins:e.record(PluginIdSchema(),InstalledPluginSchema()).describe("Map of plugin IDs to their installation metadata")}));export const PluginScopeSchema=o(()=>e.enum(["managed","user","project","local"]));export const PluginInstallationEntrySchema=o(()=>e.object({scope:PluginScopeSchema().describe("Installation scope"),projectPath:e.string().optional().describe("Project path (required for project/local scopes)"),installPath:e.string().describe("Absolute path to the versioned plugin directory"),version:e.string().optional().describe("Currently installed version"),installedAt:e.string().optional().describe("ISO 8601 timestamp of installation"),lastUpdated:e.string().optional().describe("ISO 8601 timestamp of last update"),gitCommitSha:e.string().optional().describe("Git commit SHA for git-based plugins")}));export const InstalledPluginsFileSchemaV2=o(()=>e.object({version:e.literal(2).describe("Schema version 2"),plugins:e.record(PluginIdSchema(),e.array(PluginInstallationEntrySchema())).describe("Map of plugin IDs to arrays of installation entries")}));export const InstalledPluginsFileSchema=o(()=>e.union([InstalledPluginsFileSchemaV1(),InstalledPluginsFileSchemaV2()]));export const KnownMarketplaceSchema=o(()=>e.object({source:MarketplaceSourceSchema().describe("Where to fetch the marketplace from"),installLocation:e.string().describe("Local cache path where marketplace manifest is stored"),lastUpdated:e.string().describe("ISO 8601 timestamp of last marketplace refresh"),autoUpdate:e.boolean().optional().describe("Whether to automatically update this marketplace and its installed plugins on startup")}));export const KnownMarketplacesFileSchema=o(()=>e.record(e.string(),KnownMarketplaceSchema()));
1
+ import{z as e}from"zod/v4";import{HooksSchema as t}from"../../schemas/hooks.js";import{McpServerConfigSchema as i}from"../../services/mcp/types.js";import{lazySchema as o}from"../lazySchema.js";export const ALLOWED_OFFICIAL_MARKETPLACE_NAMES=new Set(["claude-code-marketplace","claude-code-plugins","claude-plugins-official","anthropic-marketplace","anthropic-plugins","agent-skills","life-sciences","knowledge-work-plugins"]);const a=new Set(["knowledge-work-plugins"]);export function isMarketplaceAutoUpdate(e,t){const i=e.toLowerCase();return t.autoUpdate??(ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(i)&&!a.has(i))}export const BLOCKED_OFFICIAL_NAME_PATTERN=/(?:official[^a-z0-9]*(contextcompany|claude)|(?:contextcompany|claude)[^a-z0-9]*official|^(?:contextcompany|claude)[^a-z0-9]*(marketplace|plugins|official))/i;const r=/[^\u0020-\u007E]/;export function isBlockedOfficialName(e){return!ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(e.toLowerCase())&&(!!r.test(e)||BLOCKED_OFFICIAL_NAME_PATTERN.test(e))}export const OFFICIAL_GITHUB_ORG="anthropics";export function validateOfficialNameSource(e,t){const i=e.toLowerCase();if(!ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(i))return null;if("github"===t.source){return(t.repo||"").toLowerCase().startsWith("anthropics/")?null:`The name '${e}' is reserved for official ContextCompany marketplaces. Only repositories from 'github.com/anthropics/' can use this name.`}if("git"===t.source&&t.url){const i=t.url.toLowerCase(),o=i.includes("github.com/anthropics/"),a=i.includes("git@github.com:anthropics/");return o||a?null:`The name '${e}' is reserved for official ContextCompany marketplaces. Only repositories from 'github.com/anthropics/' can use this name.`}return`The name '${e}' is reserved for official ContextCompany marketplaces and can only be used with GitHub sources from the 'anthropics' organization.`}const n=o(()=>e.string().startsWith("./")),s=o(()=>n().endsWith(".json")),l=o(()=>e.union([n().refine(e=>e.endsWith(".mcpb")||e.endsWith(".dxt"),{message:"MCPB file path must end with .mcpb or .dxt"}).describe("Path to MCPB file relative to plugin root"),e.string().url().refine(e=>e.endsWith(".mcpb")||e.endsWith(".dxt"),{message:"MCPB URL must end with .mcpb or .dxt"}).describe("URL to MCPB file")])),c=o(()=>n().endsWith(".md")),d=o(()=>e.union([c(),n()])),p=o(()=>e.string().min(1,"Marketplace must have a name").refine(e=>!e.includes(" "),{message:'Marketplace name cannot contain spaces. Use kebab-case (e.g., "my-marketplace")'}).refine(e=>!e.includes("/")&&!e.includes("\\")&&!e.includes("..")&&"."!==e,{message:'Marketplace name cannot contain path separators (/ or \\), ".." sequences, or be "."'}).refine(e=>!isBlockedOfficialName(e),{message:"Marketplace name impersonates an official ContextCompany/Claude marketplace"}).refine(e=>"inline"!==e.toLowerCase(),{message:'Marketplace name "inline" is reserved for --plugin-dir session plugins'}).refine(e=>"builtin"!==e.toLowerCase(),{message:'Marketplace name "builtin" is reserved for built-in plugins'}));export const PluginAuthorSchema=o(()=>e.object({name:e.string().min(1,"Author name cannot be empty").describe("Display name of the plugin author or organization"),email:e.string().optional().describe("Contact email for support or feedback"),url:e.string().optional().describe("Website, GitHub profile, or organization URL")}));const u=o(()=>e.object({name:e.string().min(1,"Plugin name cannot be empty").refine(e=>!e.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Unique identifier for the plugin, used for namespacing (prefer kebab-case)"),version:e.string().optional().describe("Semantic version (e.g., 1.2.3) following semver.org specification"),description:e.string().optional().describe("Brief, user-facing explanation of what the plugin provides"),author:PluginAuthorSchema().optional().describe("Information about the plugin creator or maintainer"),homepage:e.string().url().optional().describe("Plugin homepage or documentation URL"),repository:e.string().optional().describe("Source code repository URL"),license:e.string().optional().describe("SPDX license identifier (e.g., MIT, Apache-2.0)"),keywords:e.array(e.string()).optional().describe("Tags for plugin discovery and categorization"),dependencies:e.array(DependencyRefSchema()).optional().describe('Plugins that must be enabled for this plugin to function. Bare names (no "@marketplace") are resolved against the declaring plugin\'s own marketplace.')}));export const PluginHooksSchema=o(()=>e.object({description:e.string().optional().describe("Brief, user-facing explanation of what these hooks provide"),hooks:e.lazy(()=>t()).describe("The hooks provided by the plugin, in the same format as the one used for settings")}));const g=o(()=>e.object({hooks:e.union([s().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),e.lazy(()=>t()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)"),e.array(e.union([s().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),e.lazy(()=>t()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)")]))])}));export const CommandMetadataSchema=o(()=>e.object({source:d().optional().describe("Path to command markdown file, relative to plugin root"),content:e.string().optional().describe("Inline markdown content for the command"),description:e.string().optional().describe("Command description override"),argumentHint:e.string().optional().describe('Hint for command arguments (e.g., "[file]")'),model:e.string().optional().describe("Default model for this command"),allowedTools:e.array(e.string()).optional().describe("Tools allowed when command runs")}).refine(e=>e.source&&!e.content||!e.source&&e.content,{message:'Command must have either "source" (file path) or "content" (inline markdown), but not both'}));const m=o(()=>e.object({commands:e.union([d().describe("Path to additional command file or skill directory (in addition to those in the commands/ directory, if it exists), relative to the plugin root"),e.array(d().describe("Path to additional command file or skill directory (in addition to those in the commands/ directory, if it exists), relative to the plugin root")).describe("List of paths to additional command files or skill directories"),e.record(e.string(),CommandMetadataSchema()).describe('Object mapping of command names to their metadata and source files. Command name becomes the slash command name (e.g., "about" → "/plugin:about")')])})),h=o(()=>e.object({agents:e.union([c().describe("Path to additional agent file (in addition to those in the agents/ directory, if it exists), relative to the plugin root"),e.array(c().describe("Path to additional agent file (in addition to those in the agents/ directory, if it exists), relative to the plugin root")).describe("List of paths to additional agent files")])})),b=o(()=>e.object({skills:e.union([n().describe("Path to additional skill directory (in addition to those in the skills/ directory, if it exists), relative to the plugin root"),e.array(n().describe("Path to additional skill directory (in addition to those in the skills/ directory, if it exists), relative to the plugin root")).describe("List of paths to additional skill directories")])})),f=o(()=>e.object({outputStyles:e.union([n().describe("Path to additional output styles directory or file (in addition to those in the output-styles/ directory, if it exists), relative to the plugin root"),e.array(n().describe("Path to additional output styles directory or file (in addition to those in the output-styles/ directory, if it exists), relative to the plugin root")).describe("List of paths to additional output styles directories or files")])})),y=o(()=>e.string().min(1)),k=o(()=>e.string().min(2).refine(e=>e.startsWith("."),{message:'File extensions must start with dot (e.g., ".ts", not "ts")'})),v=o(()=>e.object({mcpServers:e.union([s().describe("MCP servers to include in the plugin (in addition to those in the .mcp.json file, if it exists)"),l().describe("Path or URL to MCPB file containing MCP server configuration"),e.record(e.string(),i()).describe("MCP server configurations keyed by server name"),e.array(e.union([s().describe("Path to MCP servers configuration file"),l().describe("Path or URL to MCPB file"),e.record(e.string(),i()).describe("Inline MCP server configurations")])).describe("Array of MCP server configurations (paths, MCPB files, or inline definitions)")])})),P=o(()=>e.object({type:e.enum(["string","number","boolean","directory","file"]).describe("Type of the configuration value"),title:e.string().describe("Human-readable label shown in the config dialog"),description:e.string().describe("Help text shown beneath the field in the config dialog"),required:e.boolean().optional().describe("If true, validation fails when this field is empty"),default:e.union([e.string(),e.number(),e.boolean(),e.array(e.string())]).optional().describe("Default value used when the user provides nothing"),multiple:e.boolean().optional().describe("For string type: allow an array of strings"),sensitive:e.boolean().optional().describe("If true, masks dialog input and stores value in secure storage (keychain/credentials file) instead of settings.json"),min:e.number().optional().describe("Minimum value (number type only)"),max:e.number().optional().describe("Maximum value (number type only)")}).strict()),S=o(()=>e.object({userConfig:e.record(e.string().regex(/^[A-Za-z_]\w*$/,"Option keys must be valid identifiers (letters, digits, underscore; no leading digit) — they become CLAUDE_PLUGIN_OPTION_<KEY> env vars in hooks"),P()).optional().describe("User-configurable values this plugin needs. Prompted at enable time. Non-sensitive values saved to settings.json; sensitive values to secure storage (macOS keychain or .credentials.json). Available as ${user_config.KEY} in MCP/LSP server config, hook commands, and (non-sensitive only) skill/agent content. Note: sensitive values share a single keychain entry with OAuth tokens — keep secret counts small to stay under the ~2KB stdin-safe limit (see INC-3028).")})),w=o(()=>e.object({channels:e.array(e.object({server:e.string().min(1).describe("Name of the MCP server this channel binds to. Must match a key in this plugin's mcpServers."),displayName:e.string().optional().describe('Human-readable name shown in the config dialog title (e.g., "Telegram"). Defaults to the server name.'),userConfig:e.record(e.string(),P()).optional().describe("Fields to prompt the user for when enabling this plugin in assistant mode. Saved values are substituted into ${user_config.KEY} references in the mcpServers env.")}).strict()).describe("Channels this plugin provides. Each entry declares an MCP server as a message channel and optionally specifies user configuration to prompt for at enable time.")}));export const LspServerConfigSchema=o(()=>e.strictObject({command:e.string().min(1).refine(e=>!(e.includes(" ")&&!e.startsWith("/")),{message:"Command should not contain spaces. Use args array for arguments."}).describe('Command to execute the LSP server (e.g., "typescript-language-server")'),args:e.array(y()).optional().describe("Command-line arguments to pass to the server"),extensionToLanguage:e.record(k(),y()).refine(e=>Object.keys(e).length>0,{message:"extensionToLanguage must have at least one mapping"}).describe("Mapping from file extension to LSP language ID. File extensions and languages are derived from this mapping."),transport:e.enum(["stdio","socket"]).default("stdio").describe("Communication transport mechanism"),env:e.record(e.string(),e.string()).optional().describe("Environment variables to set when starting the server"),initializationOptions:e.unknown().optional().describe("Initialization options passed to the server during initialization"),settings:e.unknown().optional().describe("Settings passed to the server via workspace/didChangeConfiguration"),workspaceFolder:e.string().optional().describe("Workspace folder path to use for the server"),startupTimeout:e.number().int().positive().optional().describe("Maximum time to wait for server startup (milliseconds)"),shutdownTimeout:e.number().int().positive().optional().describe("Maximum time to wait for graceful shutdown (milliseconds)"),restartOnCrash:e.boolean().optional().describe("Whether to restart the server if it crashes"),maxRestarts:e.number().int().nonnegative().optional().describe("Maximum number of restart attempts before giving up")}));const x=o(()=>e.object({lspServers:e.union([s().describe("Path to .lsp.json configuration file relative to plugin root"),e.record(e.string(),LspServerConfigSchema()).describe("LSP server configurations keyed by server name"),e.array(e.union([s().describe("Path to LSP configuration file"),e.record(e.string(),LspServerConfigSchema()).describe("Inline LSP server configurations")])).describe("Array of LSP server configurations (paths or inline definitions)")])})),C=o(()=>e.string().refine(e=>!e.includes("..")&&!e.includes("//"),"Package name cannot contain path traversal patterns").refine(e=>/^@[a-z0-9][a-z0-9-._]*\/[a-z0-9][a-z0-9-._]*$/.test(e)||/^[a-z0-9][a-z0-9-._]*$/.test(e),"Invalid npm package name format")),j=o(()=>e.object({settings:e.record(e.string(),e.unknown()).optional().describe("Settings to merge when plugin is enabled. Only allowlisted keys are kept (currently: agent)")}));export const PluginManifestSchema=o(()=>e.object({...u().shape,...g().partial().shape,...m().partial().shape,...h().partial().shape,...b().partial().shape,...f().partial().shape,...w().partial().shape,...v().partial().shape,...x().partial().shape,...j().partial().shape,...S().partial().shape}));export const MarketplaceSourceSchema=o(()=>e.discriminatedUnion("source",[e.object({source:e.literal("url"),url:e.string().url().describe("Direct URL to marketplace.json file"),headers:e.record(e.string(),e.string()).optional().describe("Custom HTTP headers (e.g., for authentication)")}),e.object({source:e.literal("github"),repo:e.string().describe("GitHub repository in owner/repo format"),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:e.string().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:e.array(e.string()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.')}),e.object({source:e.literal("git"),url:e.string().describe("Full git repository URL"),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:e.string().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:e.array(e.string()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.')}),e.object({source:e.literal("npm"),package:C().describe("NPM package containing marketplace.json")}),e.object({source:e.literal("file"),path:e.string().describe("Local file path to marketplace.json")}),e.object({source:e.literal("directory"),path:e.string().describe("Local directory containing .claude-plugin/marketplace.json")}),e.object({source:e.literal("hostPattern"),hostPattern:e.string().describe('Regex pattern to match the host/domain extracted from any marketplace source type. For github sources, matches against "github.com". For git sources (SSH or HTTPS), extracts the hostname from the URL. Use in strictKnownMarketplaces to allow all marketplaces from a specific host (e.g., "^github\\.mycompany\\.com$").')}),e.object({source:e.literal("pathPattern"),pathPattern:e.string().describe('Regex pattern matched against the .path field of file and directory sources. Use in strictKnownMarketplaces to allow filesystem-based marketplaces alongside hostPattern restrictions for network sources. Use ".*" to allow all filesystem paths, or a narrower pattern (e.g., "^/opt/approved/") to restrict to specific directories.')}),e.object({source:e.literal("settings"),name:p().refine(e=>!ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(e.toLowerCase()),{message:"Reserved official marketplace names cannot be used with settings sources. validateOfficialNameSource only accepts github/git sources from anthropics/* for these names; a settings source would be rejected after loadAndCacheMarketplace has already written to disk with cleanupNeeded=false."}).describe("Marketplace name. Must match the extraKnownMarketplaces key (enforced); the synthetic manifest is written under this name. Same validation as PluginMarketplaceSchema plus reserved-name rejection — validateOfficialNameSource runs after the disk write, too late to clean up."),plugins:e.array(M()).describe("Plugin entries declared inline in settings.json"),owner:PluginAuthorSchema().optional()}).describe("Inline marketplace manifest defined directly in settings.json. The reconciler writes a synthetic marketplace.json to the cache; diffMarketplaces detects edits via isEqual on the stored source (the plugins array is inside this object, so edits surface as sourceChanged).")]));export const gitSha=o(()=>e.string().length(40).regex(/^[a-f0-9]{40}$/,"Must be a full 40-character lowercase git commit SHA"));export const PluginSourceSchema=o(()=>e.union([n().describe("Path to the plugin root, relative to the marketplace root (the directory containing .claude-plugin/, not .claude-plugin/ itself)"),e.object({source:e.literal("npm"),package:C().or(e.string()).describe("Package name (or url, or local path, or anything else that can be passed to `npm` as a package)"),version:e.string().optional().describe("Specific version or version range (e.g., ^1.0.0, ~2.1.0)"),registry:e.string().url().optional().describe("Custom NPM registry URL (defaults to using system default, likely npmjs.org)")}).describe("NPM package as plugin source"),e.object({source:e.literal("pip"),package:e.string().describe("Python package name as it appears on PyPI"),version:e.string().optional().describe("Version specifier (e.g., ==1.0.0, >=2.0.0, <3.0.0)"),registry:e.string().url().optional().describe("Custom PyPI registry URL (defaults to using system default, likely pypi.org)")}).describe("Python package as plugin source"),e.object({source:e.literal("url"),url:e.string().describe("Full git repository URL (https:// or git@)"),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:gitSha().optional().describe("Specific commit SHA to use")}),e.object({source:e.literal("github"),repo:e.string().describe("GitHub repository in owner/repo format"),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:gitSha().optional().describe("Specific commit SHA to use")}),e.object({source:e.literal("git-subdir"),url:e.string().describe("Git repository: GitHub owner/repo shorthand, https://, or git@ URL"),path:e.string().min(1).describe('Subdirectory within the repo containing the plugin (e.g., "tools/claude-plugin"). Cloned sparsely using partial clone (--filter=tree:0) to minimize bandwidth for monorepos.'),ref:e.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:gitSha().optional().describe("Specific commit SHA to use")}).describe("Plugin located in a subdirectory of a larger repository (monorepo). Only the specified subdirectory is materialized; the rest of the repo is not downloaded.")]));const M=o(()=>e.object({name:e.string().min(1,"Plugin name cannot be empty").refine(e=>!e.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Plugin name as it appears in the target repository"),source:PluginSourceSchema().describe("Where to fetch the plugin from. Must be a remote source — relative paths have no marketplace repository to resolve against."),description:e.string().optional(),version:e.string().optional(),strict:e.boolean().optional()}).refine(e=>"string"!=typeof e.source,{message:'Plugins in a settings-sourced marketplace must use remote sources (github, git-subdir, npm, url, pip). Relative-path sources like "./foo" have no marketplace repository to resolve against.'}));export function isLocalPluginSource(e){return"string"==typeof e&&e.startsWith("./")}export function isLocalMarketplaceSource(e){return"file"===e.source||"directory"===e.source}export const PluginMarketplaceEntrySchema=o(()=>PluginManifestSchema().partial().extend({name:e.string().min(1,"Plugin name cannot be empty").refine(e=>!e.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Unique identifier matching the plugin name"),source:PluginSourceSchema().describe("Where to fetch the plugin from"),category:e.string().optional().describe('Category for organizing plugins (e.g., "productivity", "development")'),tags:e.array(e.string()).optional().describe("Tags for searchability and discovery"),strict:e.boolean().optional().default(!0).describe("Require the plugin manifest to be present in the plugin folder. If false, the marketplace entry provides the manifest.")}));export const PluginMarketplaceSchema=o(()=>e.object({name:p(),owner:PluginAuthorSchema().describe("Marketplace maintainer or curator information"),plugins:e.array(PluginMarketplaceEntrySchema()).describe("Collection of available plugins in this marketplace"),forceRemoveDeletedPlugins:e.boolean().optional().describe("When true, plugins removed from this marketplace will be automatically uninstalled and flagged for users"),metadata:e.object({pluginRoot:e.string().optional().describe("Base path for relative plugin sources"),version:e.string().optional().describe("Marketplace version"),description:e.string().optional().describe("Marketplace description")}).optional().describe("Optional marketplace metadata"),allowCrossMarketplaceDependenciesOn:e.array(e.string()).optional().describe("Marketplace names whose plugins may be auto-installed as dependencies. Only the root marketplace's allowlist applies — no transitive trust.")}));export const PluginIdSchema=o(()=>e.string().regex(/^[a-z0-9][-a-z0-9._]*@[a-z0-9][-a-z0-9._]*$/i,"Plugin ID must be in format: plugin@marketplace"));const L=/^[a-z0-9][-a-z0-9._]*(@[a-z0-9][-a-z0-9._]*)?(@\^[^@]*)?$/i;export const DependencyRefSchema=o(()=>e.union([e.string().regex(L,"Dependency must be a plugin name, optionally qualified with @marketplace").transform(e=>e.replace(/@\^[^@]*$/,"")),e.object({name:e.string().min(1).regex(/^[a-z0-9][-a-z0-9._]*$/i),marketplace:e.string().min(1).regex(/^[a-z0-9][-a-z0-9._]*$/i).optional()}).loose().transform(e=>e.marketplace?`${e.name}@${e.marketplace}`:e.name)]));export const SettingsPluginEntrySchema=o(()=>e.union([PluginIdSchema(),e.object({id:PluginIdSchema().describe('Plugin identifier (e.g., "formatter@tools")'),version:e.string().optional().describe('Version constraint (e.g., "^2.0.0")'),required:e.boolean().optional().describe("If true, cannot be disabled"),config:e.record(e.string(),e.unknown()).optional().describe("Plugin-specific configuration")})]));export const InstalledPluginSchema=o(()=>e.object({version:e.string().describe("Currently installed version"),installedAt:e.string().describe("ISO 8601 timestamp of installation"),lastUpdated:e.string().optional().describe("ISO 8601 timestamp of last update"),installPath:e.string().describe("Absolute path to the installed plugin directory"),gitCommitSha:e.string().optional().describe("Git commit SHA for git-based plugins (for version tracking)")}));export const InstalledPluginsFileSchemaV1=o(()=>e.object({version:e.literal(1).describe("Schema version 1"),plugins:e.record(PluginIdSchema(),InstalledPluginSchema()).describe("Map of plugin IDs to their installation metadata")}));export const PluginScopeSchema=o(()=>e.enum(["managed","user","project","local"]));export const PluginInstallationEntrySchema=o(()=>e.object({scope:PluginScopeSchema().describe("Installation scope"),projectPath:e.string().optional().describe("Project path (required for project/local scopes)"),installPath:e.string().describe("Absolute path to the versioned plugin directory"),version:e.string().optional().describe("Currently installed version"),installedAt:e.string().optional().describe("ISO 8601 timestamp of installation"),lastUpdated:e.string().optional().describe("ISO 8601 timestamp of last update"),gitCommitSha:e.string().optional().describe("Git commit SHA for git-based plugins")}));export const InstalledPluginsFileSchemaV2=o(()=>e.object({version:e.literal(2).describe("Schema version 2"),plugins:e.record(PluginIdSchema(),e.array(PluginInstallationEntrySchema())).describe("Map of plugin IDs to arrays of installation entries")}));export const InstalledPluginsFileSchema=o(()=>e.union([InstalledPluginsFileSchemaV1(),InstalledPluginsFileSchemaV2()]));export const KnownMarketplaceSchema=o(()=>e.object({source:MarketplaceSourceSchema().describe("Where to fetch the marketplace from"),installLocation:e.string().describe("Local cache path where marketplace manifest is stored"),lastUpdated:e.string().describe("ISO 8601 timestamp of last marketplace refresh"),autoUpdate:e.boolean().optional().describe("Whether to automatically update this marketplace and its installed plugins on startup")}));export const KnownMarketplacesFileSchema=o(()=>e.record(e.string(),KnownMarketplaceSchema()));
@@ -1 +1 @@
1
- import{join as i}from"path";import{logForDebugging as a}from"../debug.js";import{getFsImplementation as e}from"../fsOperations.js";const o=/^skill\.md$/i;export async function walkPluginMarkdown(t,n,s={}){const r=e(),m=s.logLabel??"plugin";await async function scan(e,t){try{const a=await r.readdir(e);if(s.stopAtSkillDir&&a.some(i=>i.isFile()&&o.test(i.name)))return void await Promise.all(a.map(a=>a.isFile()&&a.name.toLowerCase().endsWith(".md")?n(i(e,a.name),t):void 0));await Promise.all(a.map(a=>{const o=i(e,a.name);return a.isDirectory()?scan(o,[...t,a.name]):a.isFile()&&a.name.toLowerCase().endsWith(".md")?n(o,t):void 0}))}catch(i){a(`Failed to scan ${m} directory ${e}: ${i}`,{level:"error"})}}(t,[])}
1
+ import{join as i}from"path";import{logForDebugging as a}from"../debug.js";import{getFsImplementation as e}from"../fsOperations.js";const o=/^skill\.md$/i;export async function walkPluginMarkdown(t,r,n={}){const s=e(),m=n.logLabel??"plugin";await async function scan(e,t){try{const a=await s.readdir(e);if(n.stopAtSkillDir&&a.some(i=>i.isFile()&&o.test(i.name)))return void await Promise.all(a.map(a=>a.isFile()&&a.name.toLowerCase().endsWith(".md")?r(i(e,a.name),t):void 0));await Promise.all(a.map(a=>{const o=i(e,a.name);return a.isDirectory()?scan(o,[...t,a.name]):a.isFile()&&a.name.toLowerCase().endsWith(".md")?r(o,t):void 0}))}catch(i){a(`Failed to scan ${m} directory ${e}: ${i}`,{level:"error"})}}(t,[])}
@@ -1 +1 @@
1
- import{randomBytes as t}from"crypto";import{chmod as e,lstat as i,readdir as n,readFile as a,rename as r,rm as o,stat as c,writeFile as s}from"fs/promises";import{tmpdir as l}from"os";import{basename as p,dirname as u,join as h}from"path";import{logForDebugging as f}from"../debug.js";import{parseZipModes as g,unzipFile as m}from"../dxt/zip.js";import{isEnvTruthy as d}from"../envUtils.js";import{getFsImplementation as w}from"../fsOperations.js";import{expandTilde as y}from"../permissions/pathValidation.js";export function isPluginZipCacheEnabled(){return d(process.env.CONTEXT_CODE_PLUGIN_USE_ZIP_CACHE)||d(process.env.CLAUDE_CODE_PLUGIN_USE_ZIP_CACHE)}export function getPluginZipCachePath(){if(!isPluginZipCacheEnabled())return;const t=process.env.CONTEXT_CODE_PLUGIN_CACHE_DIR??process.env.CLAUDE_CODE_PLUGIN_CACHE_DIR;return t?y(t):void 0}export function getZipCacheKnownMarketplacesPath(){const t=getPluginZipCachePath();if(!t)throw new Error("Plugin zip cache is not enabled");return h(t,"known_marketplaces.json")}export function getZipCacheInstalledPluginsPath(){const t=getPluginZipCachePath();if(!t)throw new Error("Plugin zip cache is not enabled");return h(t,"installed_plugins.json")}export function getZipCacheMarketplacesDir(){const t=getPluginZipCachePath();if(!t)throw new Error("Plugin zip cache is not enabled");return h(t,"marketplaces")}export function getZipCachePluginsDir(){const t=getPluginZipCachePath();if(!t)throw new Error("Plugin zip cache is not enabled");return h(t,"plugins")}let C=null,P=null;export async function getSessionPluginCachePath(){return C||(P||(P=(async()=>{const e=t(8).toString("hex"),i=h(l(),`claude-plugin-session-${e}`);return await w().mkdir(i),C=i,f(`Created session plugin cache at ${i}`),i})()),P)}export async function cleanupSessionPluginCache(){if(C)try{await o(C,{recursive:!0,force:!0}),f(`Cleaned up session plugin cache at ${C}`)}catch(t){f(`Failed to clean up session plugin cache: ${t}`)}finally{C=null,P=null}}export function resetSessionPluginCache(){C=null,P=null}export async function atomicWriteToZipCache(e,i){const n=u(e);await w().mkdir(n);const a=`.${p(e)}.tmp.${t(4).toString("hex")}`,c=h(n,a);try{"string"==typeof i?await s(c,i,{encoding:"utf-8"}):await s(c,i),await r(c,e)}catch(t){try{await o(c,{force:!0})}catch{}throw t}}export async function createZipFromDirectory(t){const e={},i=new Set;await collectFilesForZip(t,"",e,i);const{zipSync:n}=await import("fflate"),a=n(e,{level:6});return f(`Created ZIP from ${t}: ${Object.keys(e).length} files, ${a.length} bytes`),a}async function collectFilesForZip(t,e,r,o){const s=e?h(t,e):t;let l;try{l=await n(s)}catch{return}try{const t=await c(s,{bigint:!0});if(0n!==t.dev||0n!==t.ino){const e=`${t.dev}:${t.ino}`;if(o.has(e))return void f(`Skipping symlink cycle at ${s}`);o.add(e)}}catch{return}for(const n of l){if(".git"===n)continue;const l=h(s,n),p=e?`${e}/${n}`:n;let u;try{u=await i(l)}catch{continue}if(u.isSymbolicLink())try{const t=await c(l);if(t.isDirectory())continue;u=t}catch{continue}if(u.isDirectory())await collectFilesForZip(t,p,r,o);else if(u.isFile())try{const t=await a(l);r[p]=[new Uint8Array(t),{os:3,attrs:(65535&u.mode)<<16}]}catch(t){f(`Failed to read file for zip: ${p}: ${t}`)}}}export async function extractZipToDirectory(t,i){const n=await w().readFileBytes(t),a=await m(n),r=g(n);await w().mkdir(i);for(const[t,n]of Object.entries(a)){if(t.endsWith("/")){await w().mkdir(h(i,t));continue}const a=h(i,t);await w().mkdir(u(a)),await s(a,n);const o=r[t];o&&73&o&&await e(a,511&o).catch(()=>{})}f(`Extracted ZIP to ${i}: ${Object.keys(a).length} entries`)}export async function convertDirectoryToZipInPlace(t,e){const i=await createZipFromDirectory(t);await atomicWriteToZipCache(e,i),await o(t,{recursive:!0,force:!0})}export function getMarketplaceJsonRelativePath(t){const e=t.replace(/[^a-zA-Z0-9\-_]/g,"-");return h("marketplaces",`${e}.json`)}export function isMarketplaceSourceSupportedByZipCache(t){return["github","git","url","settings"].includes(t.source)}
1
+ import{randomBytes as t}from"crypto";import{chmod as e,lstat as i,readdir as n,readFile as r,rename as o,rm as a,stat as c,writeFile as s}from"fs/promises";import{tmpdir as l}from"os";import{basename as p,dirname as u,join as f}from"path";import{logForDebugging as h}from"../debug.js";import{parseZipModes as g,unzipFile as m}from"../dxt/zip.js";import{isEnvTruthy as w}from"../envUtils.js";import{getFsImplementation as d}from"../fsOperations.js";import{expandTilde as C}from"../permissions/pathValidation.js";export function isPluginZipCacheEnabled(){return w(process.env.CONTEXT_CODE_PLUGIN_USE_ZIP_CACHE)||w(process.env.CLAUDE_CODE_PLUGIN_USE_ZIP_CACHE)}export function getPluginZipCachePath(){if(!isPluginZipCacheEnabled())return;const t=process.env.CONTEXT_CODE_PLUGIN_CACHE_DIR??process.env.CLAUDE_CODE_PLUGIN_CACHE_DIR;return t?C(t):void 0}export function getZipCacheKnownMarketplacesPath(){const t=getPluginZipCachePath();if(!t)throw new Error("Plugin zip cache is not enabled");return f(t,"known_marketplaces.json")}export function getZipCacheInstalledPluginsPath(){const t=getPluginZipCachePath();if(!t)throw new Error("Plugin zip cache is not enabled");return f(t,"installed_plugins.json")}export function getZipCacheMarketplacesDir(){const t=getPluginZipCachePath();if(!t)throw new Error("Plugin zip cache is not enabled");return f(t,"marketplaces")}export function getZipCachePluginsDir(){const t=getPluginZipCachePath();if(!t)throw new Error("Plugin zip cache is not enabled");return f(t,"plugins")}let y=null,P=null;export async function getSessionPluginCachePath(){return y||(P||(P=(async()=>{const e=t(8).toString("hex"),i=f(l(),`claude-plugin-session-${e}`);return await d().mkdir(i),y=i,h(`Created session plugin cache at ${i}`),i})()),P)}export async function cleanupSessionPluginCache(){if(y)try{await a(y,{recursive:!0,force:!0}),h(`Cleaned up session plugin cache at ${y}`)}catch(t){h(`Failed to clean up session plugin cache: ${t}`)}finally{y=null,P=null}}export function resetSessionPluginCache(){y=null,P=null}export async function atomicWriteToZipCache(e,i){const n=u(e);await d().mkdir(n);const r=`.${p(e)}.tmp.${t(4).toString("hex")}`,c=f(n,r);try{"string"==typeof i?await s(c,i,{encoding:"utf-8"}):await s(c,i),await o(c,e)}catch(t){try{await a(c,{force:!0})}catch{}throw t}}export async function createZipFromDirectory(t){const e={},i=new Set;await collectFilesForZip(t,"",e,i);const{zipSync:n}=await import("fflate"),r=n(e,{level:6});return h(`Created ZIP from ${t}: ${Object.keys(e).length} files, ${r.length} bytes`),r}async function collectFilesForZip(t,e,o,a){const s=e?f(t,e):t;let l;try{l=await n(s)}catch{return}try{const t=await c(s,{bigint:!0});if(0n!==t.dev||0n!==t.ino){const e=`${t.dev}:${t.ino}`;if(a.has(e))return void h(`Skipping symlink cycle at ${s}`);a.add(e)}}catch{return}for(const n of l){if(".git"===n)continue;const l=f(s,n),p=e?`${e}/${n}`:n;let u;try{u=await i(l)}catch{continue}if(u.isSymbolicLink())try{const t=await c(l);if(t.isDirectory())continue;u=t}catch{continue}if(u.isDirectory())await collectFilesForZip(t,p,o,a);else if(u.isFile())try{const t=await r(l);o[p]=[new Uint8Array(t),{os:3,attrs:(65535&u.mode)<<16}]}catch(t){h(`Failed to read file for zip: ${p}: ${t}`)}}}export async function extractZipToDirectory(t,i){const n=await d().readFileBytes(t),r=await m(n),o=g(n);await d().mkdir(i);for(const[t,n]of Object.entries(r)){if(t.endsWith("/")){await d().mkdir(f(i,t));continue}const r=f(i,t);await d().mkdir(u(r)),await s(r,n);const a=o[t];a&&73&a&&await e(r,511&a).catch(()=>{})}h(`Extracted ZIP to ${i}: ${Object.keys(r).length} entries`)}export async function convertDirectoryToZipInPlace(t,e){const i=await createZipFromDirectory(t);await atomicWriteToZipCache(e,i),await a(t,{recursive:!0,force:!0})}export function getMarketplaceJsonRelativePath(t){const e=t.replace(/[^a-zA-Z0-9\-_]/g,"-");return f("marketplaces",`${e}.json`)}export function isMarketplaceSourceSupportedByZipCache(t){return["github","git","url","settings"].includes(t.source)}
@@ -1 +1 @@
1
- import{execa as e}from"execa";import{logForDebugging as t}from"../debug.js";import{memoizeWithLRU as n}from"../memoize.js";import{getCachedPowerShellPath as s}from"../shell/powershellDetection.js";import{jsonParse as r}from"../slowOperations.js";export const PARSE_SCRIPT_BODY="\nif (-not $EncodedCommand) {\n Write-Output '{\"valid\":false,\"errors\":[{\"message\":\"No command provided\",\"errorId\":\"NoInput\"}],\"statements\":[],\"variables\":[],\"hasStopParsing\":false,\"originalCommand\":\"\"}'\n exit 0\n}\n\n$Command = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedCommand))\n\n$tokens = $null\n$parseErrors = $null\n$ast = [System.Management.Automation.Language.Parser]::ParseInput(\n $Command,\n [ref]$tokens,\n [ref]$parseErrors\n)\n\n$allVariables = [System.Collections.ArrayList]::new()\n\nfunction Get-RawCommandElements {\n param([System.Management.Automation.Language.CommandAst]$CmdAst)\n $elems = [System.Collections.ArrayList]::new()\n foreach ($ce in $CmdAst.CommandElements) {\n $ceData = @{ type = $ce.GetType().Name; text = $ce.Extent.Text }\n if ($ce.PSObject.Properties['Value'] -and $null -ne $ce.Value -and $ce.Value -is [string]) {\n $ceData.value = $ce.Value\n }\n if ($ce -is [System.Management.Automation.Language.CommandExpressionAst]) {\n $ceData.expressionType = $ce.Expression.GetType().Name\n }\n $a=$ce.Argument;if($a){$ceData.children=@(@{type=$a.GetType().Name;text=$a.Extent.Text})}\n [void]$elems.Add($ceData)\n }\n return $elems\n}\n\nfunction Get-RawRedirections {\n param($Redirections)\n $result = [System.Collections.ArrayList]::new()\n foreach ($redir in $Redirections) {\n $redirData = @{ type = $redir.GetType().Name }\n if ($redir -is [System.Management.Automation.Language.FileRedirectionAst]) {\n $redirData.append = [bool]$redir.Append\n $redirData.fromStream = $redir.FromStream.ToString()\n $redirData.locationText = $redir.Location.Extent.Text\n }\n [void]$result.Add($redirData)\n }\n return $result\n}\n\nfunction Get-SecurityPatterns($A) {\n $p = @{}\n foreach ($n in $A.FindAll({ param($x)\n $x -is [System.Management.Automation.Language.MemberExpressionAst] -or\n $x -is [System.Management.Automation.Language.SubExpressionAst] -or\n $x -is [System.Management.Automation.Language.ArrayExpressionAst] -or\n $x -is [System.Management.Automation.Language.ExpandableStringExpressionAst] -or\n $x -is [System.Management.Automation.Language.ScriptBlockExpressionAst] -or\n $x -is [System.Management.Automation.Language.ParenExpressionAst]\n }, $true)) { switch ($n.GetType().Name) {\n 'InvokeMemberExpressionAst' { $p.hasMemberInvocations = $true }\n 'MemberExpressionAst' { $p.hasMemberInvocations = $true }\n 'SubExpressionAst' { $p.hasSubExpressions = $true }\n 'ArrayExpressionAst' { $p.hasSubExpressions = $true }\n 'ParenExpressionAst' { $p.hasSubExpressions = $true }\n 'ExpandableStringExpressionAst' { $p.hasExpandableStrings = $true }\n 'ScriptBlockExpressionAst' { $p.hasScriptBlocks = $true }\n }}\n if ($p.Count -gt 0) { return $p }\n return $null\n}\n\n$varExprs = $ast.FindAll({ param($node) $node -is [System.Management.Automation.Language.VariableExpressionAst] }, $true)\nforeach ($v in $varExprs) {\n [void]$allVariables.Add(@{\n path = $v.VariablePath.ToString()\n isSplatted = [bool]$v.Splatted\n })\n}\n\n$typeLiterals = [System.Collections.ArrayList]::new()\nforeach ($t in $ast.FindAll({ param($n)\n $n -is [System.Management.Automation.Language.TypeExpressionAst] -or\n $n -is [System.Management.Automation.Language.TypeConstraintAst]\n}, $true)) { [void]$typeLiterals.Add($t.TypeName.FullName) }\n\n$hasStopParsing = $false\n$tk = [System.Management.Automation.Language.TokenKind]\nforeach ($tok in $tokens) {\n if ($tok.Kind -eq $tk::MinusMinus) { $hasStopParsing = $true; break }\n if ($tok.Kind -eq $tk::Generic -and ($tok.Text -replace '[–—―]','-') -eq '--%') {\n $hasStopParsing = $true; break\n }\n}\n\n$statements = [System.Collections.ArrayList]::new()\n\nfunction Process-BlockStatements {\n param($Block)\n if (-not $Block) { return }\n\n foreach ($stmt in $Block.Statements) {\n $statement = @{\n type = $stmt.GetType().Name\n text = $stmt.Extent.Text\n }\n\n if ($stmt -is [System.Management.Automation.Language.PipelineAst]) {\n $elements = [System.Collections.ArrayList]::new()\n foreach ($element in $stmt.PipelineElements) {\n $elemData = @{\n type = $element.GetType().Name\n text = $element.Extent.Text\n }\n\n if ($element -is [System.Management.Automation.Language.CommandAst]) {\n $elemData.commandElements = @(Get-RawCommandElements -CmdAst $element)\n $elemData.redirections = @(Get-RawRedirections -Redirections $element.Redirections)\n } elseif ($element -is [System.Management.Automation.Language.CommandExpressionAst]) {\n $elemData.expressionType = $element.Expression.GetType().Name\n $elemData.redirections = @(Get-RawRedirections -Redirections $element.Redirections)\n }\n\n [void]$elements.Add($elemData)\n }\n $statement.elements = @($elements)\n\n $allNestedCmds = $stmt.FindAll(\n { param($node) $node -is [System.Management.Automation.Language.CommandAst] },\n $true\n )\n $nestedCmds = [System.Collections.ArrayList]::new()\n foreach ($cmd in $allNestedCmds) {\n if ($cmd.Parent -eq $stmt) { continue }\n $nested = @{\n type = $cmd.GetType().Name\n text = $cmd.Extent.Text\n commandElements = @(Get-RawCommandElements -CmdAst $cmd)\n redirections = @(Get-RawRedirections -Redirections $cmd.Redirections)\n }\n [void]$nestedCmds.Add($nested)\n }\n if ($nestedCmds.Count -gt 0) {\n $statement.nestedCommands = @($nestedCmds)\n }\n $r = $stmt.FindAll({param($n) $n -is [System.Management.Automation.Language.FileRedirectionAst]}, $true)\n if ($r.Count -gt 0) {\n $rr = @(Get-RawRedirections -Redirections $r)\n $statement.redirections = if ($statement.redirections) { @($statement.redirections) + $rr } else { $rr }\n }\n } else {\n $nestedCmdAsts = $stmt.FindAll(\n { param($node) $node -is [System.Management.Automation.Language.CommandAst] },\n $true\n )\n $nested = [System.Collections.ArrayList]::new()\n foreach ($cmd in $nestedCmdAsts) {\n [void]$nested.Add(@{\n type = 'CommandAst'\n text = $cmd.Extent.Text\n commandElements = @(Get-RawCommandElements -CmdAst $cmd)\n redirections = @(Get-RawRedirections -Redirections $cmd.Redirections)\n })\n }\n if ($nested.Count -gt 0) {\n $statement.nestedCommands = @($nested)\n }\n $r = $stmt.FindAll({param($n) $n -is [System.Management.Automation.Language.FileRedirectionAst]}, $true)\n if ($r.Count -gt 0) { $statement.redirections = @(Get-RawRedirections -Redirections $r) }\n }\n\n $sp = Get-SecurityPatterns $stmt\n if ($sp) { $statement.securityPatterns = $sp }\n\n [void]$statements.Add($statement)\n }\n\n if ($Block.Traps) {\n foreach ($trap in $Block.Traps) {\n $statement = @{\n type = 'TrapStatementAst'\n text = $trap.Extent.Text\n }\n $nestedCmdAsts = $trap.FindAll(\n { param($node) $node -is [System.Management.Automation.Language.CommandAst] },\n $true\n )\n $nestedCmds = [System.Collections.ArrayList]::new()\n foreach ($cmd in $nestedCmdAsts) {\n $nested = @{\n type = $cmd.GetType().Name\n text = $cmd.Extent.Text\n commandElements = @(Get-RawCommandElements -CmdAst $cmd)\n redirections = @(Get-RawRedirections -Redirections $cmd.Redirections)\n }\n [void]$nestedCmds.Add($nested)\n }\n if ($nestedCmds.Count -gt 0) {\n $statement.nestedCommands = @($nestedCmds)\n }\n $r = $trap.FindAll({param($n) $n -is [System.Management.Automation.Language.FileRedirectionAst]}, $true)\n if ($r.Count -gt 0) { $statement.redirections = @(Get-RawRedirections -Redirections $r) }\n $sp = Get-SecurityPatterns $trap\n if ($sp) { $statement.securityPatterns = $sp }\n [void]$statements.Add($statement)\n }\n }\n}\n\nProcess-BlockStatements -Block $ast.BeginBlock\nProcess-BlockStatements -Block $ast.ProcessBlock\nProcess-BlockStatements -Block $ast.EndBlock\nProcess-BlockStatements -Block $ast.CleanBlock\nProcess-BlockStatements -Block $ast.DynamicParamBlock\n\nif ($ast.ParamBlock) {\n $pb = $ast.ParamBlock\n $pn = [System.Collections.ArrayList]::new()\n foreach ($c in $pb.FindAll({param($n) $n -is [System.Management.Automation.Language.CommandAst]}, $true)) {\n [void]$pn.Add(@{type='CommandAst';text=$c.Extent.Text;commandElements=@(Get-RawCommandElements -CmdAst $c);redirections=@(Get-RawRedirections -Redirections $c.Redirections)})\n }\n $pr = $pb.FindAll({param($n) $n -is [System.Management.Automation.Language.FileRedirectionAst]}, $true)\n $ps = Get-SecurityPatterns $pb\n if ($pn.Count -gt 0 -or $pr.Count -gt 0 -or $ps) {\n $st = @{type='ParamBlockAst';text=$pb.Extent.Text}\n if ($pn.Count -gt 0) { $st.nestedCommands = @($pn) }\n if ($pr.Count -gt 0) { $st.redirections = @(Get-RawRedirections -Redirections $pr) }\n if ($ps) { $st.securityPatterns = $ps }\n [void]$statements.Add($st)\n }\n}\n\n$hasUsingStatements = $ast.UsingStatements -and $ast.UsingStatements.Count -gt 0\n$hasScriptRequirements = $ast.ScriptRequirements -ne $null\n\n$output = @{\n valid = ($parseErrors.Count -eq 0)\n errors = @($parseErrors | ForEach-Object {\n @{\n message = $_.Message\n errorId = $_.ErrorId\n }\n })\n statements = @($statements)\n variables = @($allVariables)\n hasStopParsing = $hasStopParsing\n originalCommand = $Command\n typeLiterals = @($typeLiterals)\n hasUsingStatements = [bool]$hasUsingStatements\n hasScriptRequirements = [bool]$hasScriptRequirements\n}\n\n$output | ConvertTo-Json -Depth 10 -Compress\n";export const WINDOWS_MAX_COMMAND_LENGTH=Math.max(0,Math.floor(1203.46875)-100);export const MAX_COMMAND_LENGTH="win32"===process.platform?WINDOWS_MAX_COMMAND_LENGTH:4500;const a={valid:!1,statements:[],variables:[],hasStopParsing:!1};function makeInvalidResult(e,t,n){return{...a,errors:[{message:t,errorId:n}],originalCommand:e}}function ensureArray(e){return null==e?[]:Array.isArray(e)?e:[e]}export function mapStatementType(e){switch(e){case"PipelineAst":return"PipelineAst";case"PipelineChainAst":return"PipelineChainAst";case"AssignmentStatementAst":return"AssignmentStatementAst";case"IfStatementAst":return"IfStatementAst";case"ForStatementAst":return"ForStatementAst";case"ForEachStatementAst":return"ForEachStatementAst";case"WhileStatementAst":return"WhileStatementAst";case"DoWhileStatementAst":return"DoWhileStatementAst";case"DoUntilStatementAst":return"DoUntilStatementAst";case"SwitchStatementAst":return"SwitchStatementAst";case"TryStatementAst":return"TryStatementAst";case"TrapStatementAst":return"TrapStatementAst";case"FunctionDefinitionAst":return"FunctionDefinitionAst";case"DataStatementAst":return"DataStatementAst";default:return"UnknownStatementAst"}}export function mapElementType(e,t){switch(e){case"ScriptBlockExpressionAst":return"ScriptBlock";case"SubExpressionAst":case"ArrayExpressionAst":case"ParenExpressionAst":return"SubExpression";case"ExpandableStringExpressionAst":return"ExpandableString";case"InvokeMemberExpressionAst":case"MemberExpressionAst":return"MemberInvocation";case"VariableExpressionAst":return"Variable";case"StringConstantExpressionAst":case"ConstantExpressionAst":return"StringConstant";case"CommandParameterAst":return"Parameter";case"CommandExpressionAst":return t?mapElementType(t):"Other";default:return"Other"}}export function classifyCommandName(e){return/^[A-Za-z]+-[A-Za-z][A-Za-z0-9_]*$/.test(e)?"cmdlet":/[.\\/]/.test(e)?"application":"unknown"}export function stripModulePrefix(e){const t=e.lastIndexOf("\\");return t<0||/^[A-Za-z]:/.test(e)||e.startsWith("\\\\")||e.startsWith(".\\")||e.startsWith("..\\")?e:e.substring(t+1)}export function transformCommandAst(e){const t=ensureArray(e.commandElements);let n="";const s=[],r=[],a=[];let o=!1,i="unknown";if(t.length>0){const e=t[0],m=("StringConstantExpressionAst"!==e.type&&"ExpandableStringExpressionAst"!==e.type||"string"!=typeof e.value?e.text:e.value).replace(/^['"]|['"]$/g,"");i=/[\u0080-\uFFFF]/.test(m)?"application":classifyCommandName(m),n=stripModulePrefix(m),r.push(mapElementType(e.type,e.expressionType));for(let e=1;e<t.length;e++){const n=t[e],i="StringConstantExpressionAst"===n.type||"ExpandableStringExpressionAst"===n.type;s.push(i&&null!=n.value?n.value:n.text),r.push(mapElementType(n.type,n.expressionType));const m=ensureArray(n.children);m.length>0?(o=!0,a.push(m.map(e=>({type:mapElementType(e.type),text:e.text})))):a.push(void 0)}}const m={name:n,nameType:i,elementType:"CommandAst",args:s,text:e.text,elementTypes:r,...o?{children:a}:{}},c=ensureArray(e.redirections);return c.length>0&&(m.redirections=c.map(transformRedirection)),m}export function transformExpressionElement(e){const t="ParenExpressionAst"===e.type?"ParenExpressionAst":"CommandExpressionAst",n=[mapElementType(e.type,e.expressionType)];return{name:e.text,nameType:"unknown",elementType:t,args:[],text:e.text,elementTypes:n}}export function transformRedirection(e){if("MergingRedirectionAst"===e.type)return{operator:"2>&1",target:"",isMerging:!0};const t=e.append??!1,n=e.fromStream??"Output";let s;if(t)switch(n){case"Error":s="2>>";break;case"All":s="*>>";break;default:s=">>"}else switch(n){case"Error":s="2>";break;case"All":s="*>";break;default:s=">"}return{operator:s,target:e.locationText??"",isMerging:!1}}export function transformStatement(e){const t=mapStatementType(e.type),n=[],s=[];if(e.elements){for(const t of ensureArray(e.elements))if("CommandAst"===t.type){n.push(transformCommandAst(t));for(const e of ensureArray(t.redirections))s.push(transformRedirection(e))}else{n.push(transformExpressionElement(t));for(const e of ensureArray(t.redirections))s.push(transformRedirection(e))}const t=new Set(s.map(e=>`${e.operator}\0${e.target}`));for(const n of ensureArray(e.redirections)){const e=transformRedirection(n),r=`${e.operator}\0${e.target}`;t.has(r)||(t.add(r),s.push(e))}}else{n.push({name:e.text,nameType:"unknown",elementType:"CommandExpressionAst",args:[],text:e.text});for(const t of ensureArray(e.redirections))s.push(transformRedirection(t))}let r;const a=ensureArray(e.nestedCommands);a.length>0&&(r=a.map(transformCommandAst));const o={statementType:t,commands:n,redirections:s,text:e.text,nestedCommands:r};return e.securityPatterns&&(o.securityPatterns=e.securityPatterns),o}async function parsePowerShellCommandImpl(n){const a=Buffer.byteLength(n,"utf8");if(a>MAX_COMMAND_LENGTH)return t(`PowerShell parser: command too long (${a} bytes, max ${MAX_COMMAND_LENGTH})`),makeInvalidResult(n,`Command too long for parsing (${a} bytes). Maximum supported length is ${MAX_COMMAND_LENGTH} bytes.`,"CommandTooLong");const o=await s();if(!o)return makeInvalidResult(n,"PowerShell is not available","NoPowerShell");const i=function(e){return`$EncodedCommand = '${"undefined"!=typeof Buffer?Buffer.from(e,"utf8").toString("base64"):btoa((new TextEncoder).encode(e).reduce((e,t)=>e+String.fromCharCode(t),""))}'\n${PARSE_SCRIPT_BODY}`}(n),m=function(e){if("undefined"!=typeof Buffer)return Buffer.from(e,"utf16le").toString("base64");const t=[];for(let n=0;n<e.length;n++){const s=e.charCodeAt(n);t.push(255&s,s>>8&255)}return btoa(t.map(e=>String.fromCharCode(e)).join(""))}(i),c=["-NoProfile","-NonInteractive","-NoLogo","-EncodedCommand",m],l=function(){const e=process.env.CONTEXT_CODE_PWSH_PARSE_TIMEOUT_MS??process.env.CLAUDE_CODE_PWSH_PARSE_TIMEOUT_MS;if(e){const t=parseInt(e,10);if(!isNaN(t)&&t>0)return t}return 5e3}();let p="",d="",u=null,$=!1;for(let s=0;s<2;s++){try{const t=await e(o,c,{timeout:l,reject:!1});p=t.stdout,d=t.stderr,$=t.timedOut,u=t.failed?t.exitCode??1:0}catch(e){return t(`PowerShell parser: failed to spawn pwsh: ${e instanceof Error?e.message:e}`),makeInvalidResult(n,`Failed to spawn PowerShell: ${e instanceof Error?e.message:e}`,"PwshSpawnError")}if(!$)break;t(`PowerShell parser: pwsh timed out after ${l}ms (attempt ${s+1})`)}if($)return makeInvalidResult(n,`pwsh timed out after ${l}ms (2 attempts)`,"PwshTimeout");if(0!==u)return t(`PowerShell parser: pwsh exited with code ${u}, stderr: ${d}`),makeInvalidResult(n,`pwsh exited with code ${u}: ${d}`,"PwshError");const S=p.trim();if(!S)return t("PowerShell parser: empty stdout from pwsh"),makeInvalidResult(n,"No output from PowerShell parser","EmptyOutput");try{return function(e){const t={valid:e.valid,errors:ensureArray(e.errors),statements:ensureArray(e.statements).map(transformStatement),variables:ensureArray(e.variables),hasStopParsing:e.hasStopParsing,originalCommand:e.originalCommand},n=ensureArray(e.typeLiterals);return n.length>0&&(t.typeLiterals=n),e.hasUsingStatements&&(t.hasUsingStatements=!0),e.hasScriptRequirements&&(t.hasScriptRequirements=!0),t}(r(S))}catch{return t(`PowerShell parser: invalid JSON output: ${S.slice(0,200)}`),makeInvalidResult(n,"Invalid JSON from PowerShell parser","InvalidJson")}}const o=new Set(["PwshSpawnError","PwshError","PwshTimeout","EmptyOutput","InvalidJson"]),i=n(e=>{const t=parsePowerShellCommandImpl(e);return t.then(t=>{!t.valid&&o.has(t.errors[0]?.errorId??"")&&i.cache.delete(e)}),t},e=>e,256);export{i as parsePowerShellCommand};export const COMMON_ALIASES=Object.assign(Object.create(null),{ls:"Get-ChildItem",dir:"Get-ChildItem",gci:"Get-ChildItem",cat:"Get-Content",type:"Get-Content",gc:"Get-Content",cd:"Set-Location",sl:"Set-Location",chdir:"Set-Location",pushd:"Push-Location",popd:"Pop-Location",pwd:"Get-Location",gl:"Get-Location",gi:"Get-Item",gp:"Get-ItemProperty",ni:"New-Item",mkdir:"New-Item",md:"New-Item",ri:"Remove-Item",del:"Remove-Item",rd:"Remove-Item",rmdir:"Remove-Item",rm:"Remove-Item",erase:"Remove-Item",mi:"Move-Item",mv:"Move-Item",move:"Move-Item",ci:"Copy-Item",cp:"Copy-Item",copy:"Copy-Item",cpi:"Copy-Item",si:"Set-Item",rni:"Rename-Item",ren:"Rename-Item",ps:"Get-Process",gps:"Get-Process",kill:"Stop-Process",spps:"Stop-Process",start:"Start-Process",saps:"Start-Process",sajb:"Start-Job",ipmo:"Import-Module",echo:"Write-Output",write:"Write-Output",sleep:"Start-Sleep",help:"Get-Help",man:"Get-Help",gcm:"Get-Command",gsv:"Get-Service",gv:"Get-Variable",sv:"Set-Variable",h:"Get-History",history:"Get-History",iex:"Invoke-Expression",iwr:"Invoke-WebRequest",irm:"Invoke-RestMethod",icm:"Invoke-Command",ii:"Invoke-Item",nsn:"New-PSSession",etsn:"Enter-PSSession",exsn:"Exit-PSSession",gsn:"Get-PSSession",rsn:"Remove-PSSession",cls:"Clear-Host",clear:"Clear-Host",select:"Select-Object",where:"Where-Object",foreach:"ForEach-Object","%":"ForEach-Object","?":"Where-Object",measure:"Measure-Object",ft:"Format-Table",fl:"Format-List",fw:"Format-Wide",oh:"Out-Host",ogv:"Out-GridView",ac:"Add-Content",clc:"Clear-Content",tee:"Tee-Object",epcsv:"Export-Csv",sp:"Set-ItemProperty",rp:"Remove-ItemProperty",cli:"Clear-Item",epal:"Export-Alias",sls:"Select-String"});const m=new Set(["set-location","push-location","pop-location"]),c=new Set(["cd","sl","chdir","pushd","popd"]);export function getAllCommandNames(e){const t=[];for(const n of e.statements){for(const e of n.commands)t.push(e.name.toLowerCase());if(n.nestedCommands)for(const e of n.nestedCommands)t.push(e.name.toLowerCase())}return t}export function getAllCommands(e){const t=[];for(const n of e.statements){for(const e of n.commands)t.push(e);if(n.nestedCommands)for(const e of n.nestedCommands)t.push(e)}return t}export function getAllRedirections(e){const t=[];for(const n of e.statements){for(const e of n.redirections)t.push(e);if(n.nestedCommands)for(const e of n.nestedCommands)if(e.redirections)for(const n of e.redirections)t.push(n)}return t}export function getVariablesByScope(e,t){const n=t.toLowerCase()+":";return e.variables.filter(e=>e.path.toLowerCase().startsWith(n))}export function hasCommandNamed(e,t){const n=t.toLowerCase(),s=COMMON_ALIASES[n]?.toLowerCase();for(const t of getAllCommandNames(e)){if(t===n)return!0;const e=COMMON_ALIASES[t]?.toLowerCase();if(e===n)return!0;if(s&&t===s)return!0;if(e&&s&&e===s)return!0}return!1}export function hasDirectoryChange(e){for(const t of getAllCommandNames(e))if(m.has(t)||c.has(t))return!0;return!1}export function isSingleCommand(e){const t=e.statements[0];return 1===e.statements.length&&void 0!==t&&1===t.commands.length&&(!t.nestedCommands||0===t.nestedCommands.length)}export function commandHasArg(e,t){const n=t.toLowerCase();return e.args.some(e=>e.toLowerCase()===n)}export const PS_TOKENIZER_DASH_CHARS=new Set(["-","–","—","―"]);export function isPowerShellParameter(e,t){return void 0!==t?"Parameter"===t:e.length>0&&PS_TOKENIZER_DASH_CHARS.has(e[0])}export function commandHasArgAbbreviation(e,t,n){const s=t.toLowerCase(),r=n.toLowerCase();return e.args.some(e=>{const t=e.indexOf(":",1),n=(t>0?e.slice(0,t):e).replace(/`/g,"").toLowerCase();return n.startsWith(r)&&s.startsWith(n)&&n.length<=s.length})}export function getPipelineSegments(e){return e.statements}export function isNullRedirectionTarget(e){const t=e.trim().toLowerCase();return"$null"===t||"${null}"===t}export function getFileRedirections(e){return getAllRedirections(e).filter(e=>!e.isMerging&&!isNullRedirectionTarget(e.target))}export function deriveSecurityFlags(e){const t={hasSubExpressions:!1,hasScriptBlocks:!1,hasSplatting:!1,hasExpandableStrings:!1,hasMemberInvocations:!1,hasAssignments:!1,hasStopParsing:e.hasStopParsing};function checkElements(e){if(e.elementTypes)for(const n of e.elementTypes)switch(n){case"ScriptBlock":t.hasScriptBlocks=!0;break;case"SubExpression":t.hasSubExpressions=!0;break;case"ExpandableString":t.hasExpandableStrings=!0;break;case"MemberInvocation":t.hasMemberInvocations=!0}}for(const n of e.statements){"AssignmentStatementAst"===n.statementType&&(t.hasAssignments=!0);for(const e of n.commands)checkElements(e);if(n.nestedCommands)for(const e of n.nestedCommands)checkElements(e);n.securityPatterns&&(n.securityPatterns.hasMemberInvocations&&(t.hasMemberInvocations=!0),n.securityPatterns.hasSubExpressions&&(t.hasSubExpressions=!0),n.securityPatterns.hasExpandableStrings&&(t.hasExpandableStrings=!0),n.securityPatterns.hasScriptBlocks&&(t.hasScriptBlocks=!0))}for(const n of e.variables)if(n.isSplatted){t.hasSplatting=!0;break}return t}
1
+ import{execa as e}from"execa";import{logForDebugging as t}from"../debug.js";import{memoizeWithLRU as n}from"../memoize.js";import{getCachedPowerShellPath as s}from"../shell/powershellDetection.js";import{jsonParse as r}from"../slowOperations.js";export const PARSE_SCRIPT_BODY="\nif (-not $EncodedCommand) {\n Write-Output '{\"valid\":false,\"errors\":[{\"message\":\"No command provided\",\"errorId\":\"NoInput\"}],\"statements\":[],\"variables\":[],\"hasStopParsing\":false,\"originalCommand\":\"\"}'\n exit 0\n}\n\n$Command = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedCommand))\n\n$tokens = $null\n$parseErrors = $null\n$ast = [System.Management.Automation.Language.Parser]::ParseInput(\n $Command,\n [ref]$tokens,\n [ref]$parseErrors\n)\n\n$allVariables = [System.Collections.ArrayList]::new()\n\nfunction Get-RawCommandElements {\n param([System.Management.Automation.Language.CommandAst]$CmdAst)\n $elems = [System.Collections.ArrayList]::new()\n foreach ($ce in $CmdAst.CommandElements) {\n $ceData = @{ type = $ce.GetType().Name; text = $ce.Extent.Text }\n if ($ce.PSObject.Properties['Value'] -and $null -ne $ce.Value -and $ce.Value -is [string]) {\n $ceData.value = $ce.Value\n }\n if ($ce -is [System.Management.Automation.Language.CommandExpressionAst]) {\n $ceData.expressionType = $ce.Expression.GetType().Name\n }\n $a=$ce.Argument;if($a){$ceData.children=@(@{type=$a.GetType().Name;text=$a.Extent.Text})}\n [void]$elems.Add($ceData)\n }\n return $elems\n}\n\nfunction Get-RawRedirections {\n param($Redirections)\n $result = [System.Collections.ArrayList]::new()\n foreach ($redir in $Redirections) {\n $redirData = @{ type = $redir.GetType().Name }\n if ($redir -is [System.Management.Automation.Language.FileRedirectionAst]) {\n $redirData.append = [bool]$redir.Append\n $redirData.fromStream = $redir.FromStream.ToString()\n $redirData.locationText = $redir.Location.Extent.Text\n }\n [void]$result.Add($redirData)\n }\n return $result\n}\n\nfunction Get-SecurityPatterns($A) {\n $p = @{}\n foreach ($n in $A.FindAll({ param($x)\n $x -is [System.Management.Automation.Language.MemberExpressionAst] -or\n $x -is [System.Management.Automation.Language.SubExpressionAst] -or\n $x -is [System.Management.Automation.Language.ArrayExpressionAst] -or\n $x -is [System.Management.Automation.Language.ExpandableStringExpressionAst] -or\n $x -is [System.Management.Automation.Language.ScriptBlockExpressionAst] -or\n $x -is [System.Management.Automation.Language.ParenExpressionAst]\n }, $true)) { switch ($n.GetType().Name) {\n 'InvokeMemberExpressionAst' { $p.hasMemberInvocations = $true }\n 'MemberExpressionAst' { $p.hasMemberInvocations = $true }\n 'SubExpressionAst' { $p.hasSubExpressions = $true }\n 'ArrayExpressionAst' { $p.hasSubExpressions = $true }\n 'ParenExpressionAst' { $p.hasSubExpressions = $true }\n 'ExpandableStringExpressionAst' { $p.hasExpandableStrings = $true }\n 'ScriptBlockExpressionAst' { $p.hasScriptBlocks = $true }\n }}\n if ($p.Count -gt 0) { return $p }\n return $null\n}\n\n$varExprs = $ast.FindAll({ param($node) $node -is [System.Management.Automation.Language.VariableExpressionAst] }, $true)\nforeach ($v in $varExprs) {\n [void]$allVariables.Add(@{\n path = $v.VariablePath.ToString()\n isSplatted = [bool]$v.Splatted\n })\n}\n\n$typeLiterals = [System.Collections.ArrayList]::new()\nforeach ($t in $ast.FindAll({ param($n)\n $n -is [System.Management.Automation.Language.TypeExpressionAst] -or\n $n -is [System.Management.Automation.Language.TypeConstraintAst]\n}, $true)) { [void]$typeLiterals.Add($t.TypeName.FullName) }\n\n$hasStopParsing = $false\n$tk = [System.Management.Automation.Language.TokenKind]\nforeach ($tok in $tokens) {\n if ($tok.Kind -eq $tk::MinusMinus) { $hasStopParsing = $true; break }\n if ($tok.Kind -eq $tk::Generic -and ($tok.Text -replace '[–—―]','-') -eq '--%') {\n $hasStopParsing = $true; break\n }\n}\n\n$statements = [System.Collections.ArrayList]::new()\n\nfunction Process-BlockStatements {\n param($Block)\n if (-not $Block) { return }\n\n foreach ($stmt in $Block.Statements) {\n $statement = @{\n type = $stmt.GetType().Name\n text = $stmt.Extent.Text\n }\n\n if ($stmt -is [System.Management.Automation.Language.PipelineAst]) {\n $elements = [System.Collections.ArrayList]::new()\n foreach ($element in $stmt.PipelineElements) {\n $elemData = @{\n type = $element.GetType().Name\n text = $element.Extent.Text\n }\n\n if ($element -is [System.Management.Automation.Language.CommandAst]) {\n $elemData.commandElements = @(Get-RawCommandElements -CmdAst $element)\n $elemData.redirections = @(Get-RawRedirections -Redirections $element.Redirections)\n } elseif ($element -is [System.Management.Automation.Language.CommandExpressionAst]) {\n $elemData.expressionType = $element.Expression.GetType().Name\n $elemData.redirections = @(Get-RawRedirections -Redirections $element.Redirections)\n }\n\n [void]$elements.Add($elemData)\n }\n $statement.elements = @($elements)\n\n $allNestedCmds = $stmt.FindAll(\n { param($node) $node -is [System.Management.Automation.Language.CommandAst] },\n $true\n )\n $nestedCmds = [System.Collections.ArrayList]::new()\n foreach ($cmd in $allNestedCmds) {\n if ($cmd.Parent -eq $stmt) { continue }\n $nested = @{\n type = $cmd.GetType().Name\n text = $cmd.Extent.Text\n commandElements = @(Get-RawCommandElements -CmdAst $cmd)\n redirections = @(Get-RawRedirections -Redirections $cmd.Redirections)\n }\n [void]$nestedCmds.Add($nested)\n }\n if ($nestedCmds.Count -gt 0) {\n $statement.nestedCommands = @($nestedCmds)\n }\n $r = $stmt.FindAll({param($n) $n -is [System.Management.Automation.Language.FileRedirectionAst]}, $true)\n if ($r.Count -gt 0) {\n $rr = @(Get-RawRedirections -Redirections $r)\n $statement.redirections = if ($statement.redirections) { @($statement.redirections) + $rr } else { $rr }\n }\n } else {\n $nestedCmdAsts = $stmt.FindAll(\n { param($node) $node -is [System.Management.Automation.Language.CommandAst] },\n $true\n )\n $nested = [System.Collections.ArrayList]::new()\n foreach ($cmd in $nestedCmdAsts) {\n [void]$nested.Add(@{\n type = 'CommandAst'\n text = $cmd.Extent.Text\n commandElements = @(Get-RawCommandElements -CmdAst $cmd)\n redirections = @(Get-RawRedirections -Redirections $cmd.Redirections)\n })\n }\n if ($nested.Count -gt 0) {\n $statement.nestedCommands = @($nested)\n }\n $r = $stmt.FindAll({param($n) $n -is [System.Management.Automation.Language.FileRedirectionAst]}, $true)\n if ($r.Count -gt 0) { $statement.redirections = @(Get-RawRedirections -Redirections $r) }\n }\n\n $sp = Get-SecurityPatterns $stmt\n if ($sp) { $statement.securityPatterns = $sp }\n\n [void]$statements.Add($statement)\n }\n\n if ($Block.Traps) {\n foreach ($trap in $Block.Traps) {\n $statement = @{\n type = 'TrapStatementAst'\n text = $trap.Extent.Text\n }\n $nestedCmdAsts = $trap.FindAll(\n { param($node) $node -is [System.Management.Automation.Language.CommandAst] },\n $true\n )\n $nestedCmds = [System.Collections.ArrayList]::new()\n foreach ($cmd in $nestedCmdAsts) {\n $nested = @{\n type = $cmd.GetType().Name\n text = $cmd.Extent.Text\n commandElements = @(Get-RawCommandElements -CmdAst $cmd)\n redirections = @(Get-RawRedirections -Redirections $cmd.Redirections)\n }\n [void]$nestedCmds.Add($nested)\n }\n if ($nestedCmds.Count -gt 0) {\n $statement.nestedCommands = @($nestedCmds)\n }\n $r = $trap.FindAll({param($n) $n -is [System.Management.Automation.Language.FileRedirectionAst]}, $true)\n if ($r.Count -gt 0) { $statement.redirections = @(Get-RawRedirections -Redirections $r) }\n $sp = Get-SecurityPatterns $trap\n if ($sp) { $statement.securityPatterns = $sp }\n [void]$statements.Add($statement)\n }\n }\n}\n\nProcess-BlockStatements -Block $ast.BeginBlock\nProcess-BlockStatements -Block $ast.ProcessBlock\nProcess-BlockStatements -Block $ast.EndBlock\nProcess-BlockStatements -Block $ast.CleanBlock\nProcess-BlockStatements -Block $ast.DynamicParamBlock\n\nif ($ast.ParamBlock) {\n $pb = $ast.ParamBlock\n $pn = [System.Collections.ArrayList]::new()\n foreach ($c in $pb.FindAll({param($n) $n -is [System.Management.Automation.Language.CommandAst]}, $true)) {\n [void]$pn.Add(@{type='CommandAst';text=$c.Extent.Text;commandElements=@(Get-RawCommandElements -CmdAst $c);redirections=@(Get-RawRedirections -Redirections $c.Redirections)})\n }\n $pr = $pb.FindAll({param($n) $n -is [System.Management.Automation.Language.FileRedirectionAst]}, $true)\n $ps = Get-SecurityPatterns $pb\n if ($pn.Count -gt 0 -or $pr.Count -gt 0 -or $ps) {\n $st = @{type='ParamBlockAst';text=$pb.Extent.Text}\n if ($pn.Count -gt 0) { $st.nestedCommands = @($pn) }\n if ($pr.Count -gt 0) { $st.redirections = @(Get-RawRedirections -Redirections $pr) }\n if ($ps) { $st.securityPatterns = $ps }\n [void]$statements.Add($st)\n }\n}\n\n$hasUsingStatements = $ast.UsingStatements -and $ast.UsingStatements.Count -gt 0\n$hasScriptRequirements = $ast.ScriptRequirements -ne $null\n\n$output = @{\n valid = ($parseErrors.Count -eq 0)\n errors = @($parseErrors | ForEach-Object {\n @{\n message = $_.Message\n errorId = $_.ErrorId\n }\n })\n statements = @($statements)\n variables = @($allVariables)\n hasStopParsing = $hasStopParsing\n originalCommand = $Command\n typeLiterals = @($typeLiterals)\n hasUsingStatements = [bool]$hasUsingStatements\n hasScriptRequirements = [bool]$hasScriptRequirements\n}\n\n$output | ConvertTo-Json -Depth 10 -Compress\n";export const WINDOWS_MAX_COMMAND_LENGTH=Math.max(0,Math.floor(1203.46875)-100);export const MAX_COMMAND_LENGTH="win32"===process.platform?WINDOWS_MAX_COMMAND_LENGTH:4500;const a={valid:!1,statements:[],variables:[],hasStopParsing:!1};function makeInvalidResult(e,t,n){return{...a,errors:[{message:t,errorId:n}],originalCommand:e}}function ensureArray(e){return null==e?[]:Array.isArray(e)?e:[e]}export function mapStatementType(e){switch(e){case"PipelineAst":return"PipelineAst";case"PipelineChainAst":return"PipelineChainAst";case"AssignmentStatementAst":return"AssignmentStatementAst";case"IfStatementAst":return"IfStatementAst";case"ForStatementAst":return"ForStatementAst";case"ForEachStatementAst":return"ForEachStatementAst";case"WhileStatementAst":return"WhileStatementAst";case"DoWhileStatementAst":return"DoWhileStatementAst";case"DoUntilStatementAst":return"DoUntilStatementAst";case"SwitchStatementAst":return"SwitchStatementAst";case"TryStatementAst":return"TryStatementAst";case"TrapStatementAst":return"TrapStatementAst";case"FunctionDefinitionAst":return"FunctionDefinitionAst";case"DataStatementAst":return"DataStatementAst";default:return"UnknownStatementAst"}}export function mapElementType(e,t){switch(e){case"ScriptBlockExpressionAst":return"ScriptBlock";case"SubExpressionAst":case"ArrayExpressionAst":case"ParenExpressionAst":return"SubExpression";case"ExpandableStringExpressionAst":return"ExpandableString";case"InvokeMemberExpressionAst":case"MemberExpressionAst":return"MemberInvocation";case"VariableExpressionAst":return"Variable";case"StringConstantExpressionAst":case"ConstantExpressionAst":return"StringConstant";case"CommandParameterAst":return"Parameter";case"CommandExpressionAst":return t?mapElementType(t):"Other";default:return"Other"}}export function classifyCommandName(e){return/^[A-Za-z]+-[A-Za-z][A-Za-z0-9_]*$/.test(e)?"cmdlet":/[.\\/]/.test(e)?"application":"unknown"}export function stripModulePrefix(e){const t=e.lastIndexOf("\\");return t<0||/^[A-Za-z]:/.test(e)||e.startsWith("\\\\")||e.startsWith(".\\")||e.startsWith("..\\")?e:e.substring(t+1)}export function transformCommandAst(e){const t=ensureArray(e.commandElements);let n="";const s=[],r=[],a=[];let o=!1,i="unknown";if(t.length>0){const e=t[0],m=(("StringConstantExpressionAst"===e.type||"ExpandableStringExpressionAst"===e.type)&&"string"==typeof e.value?e.value:e.text).replace(/^['"]|['"]$/g,"");i=/[\u0080-\uFFFF]/.test(m)?"application":classifyCommandName(m),n=stripModulePrefix(m),r.push(mapElementType(e.type,e.expressionType));for(let e=1;e<t.length;e++){const n=t[e],i="StringConstantExpressionAst"===n.type||"ExpandableStringExpressionAst"===n.type;s.push(i&&null!=n.value?n.value:n.text),r.push(mapElementType(n.type,n.expressionType));const m=ensureArray(n.children);m.length>0?(o=!0,a.push(m.map(e=>({type:mapElementType(e.type),text:e.text})))):a.push(void 0)}}const m={name:n,nameType:i,elementType:"CommandAst",args:s,text:e.text,elementTypes:r,...o?{children:a}:{}},c=ensureArray(e.redirections);return c.length>0&&(m.redirections=c.map(transformRedirection)),m}export function transformExpressionElement(e){const t="ParenExpressionAst"===e.type?"ParenExpressionAst":"CommandExpressionAst",n=[mapElementType(e.type,e.expressionType)];return{name:e.text,nameType:"unknown",elementType:t,args:[],text:e.text,elementTypes:n}}export function transformRedirection(e){if("MergingRedirectionAst"===e.type)return{operator:"2>&1",target:"",isMerging:!0};const t=e.append??!1,n=e.fromStream??"Output";let s;if(t)switch(n){case"Error":s="2>>";break;case"All":s="*>>";break;default:s=">>"}else switch(n){case"Error":s="2>";break;case"All":s="*>";break;default:s=">"}return{operator:s,target:e.locationText??"",isMerging:!1}}export function transformStatement(e){const t=mapStatementType(e.type),n=[],s=[];if(e.elements){for(const t of ensureArray(e.elements))if("CommandAst"===t.type){n.push(transformCommandAst(t));for(const e of ensureArray(t.redirections))s.push(transformRedirection(e))}else{n.push(transformExpressionElement(t));for(const e of ensureArray(t.redirections))s.push(transformRedirection(e))}const t=new Set(s.map(e=>`${e.operator}\0${e.target}`));for(const n of ensureArray(e.redirections)){const e=transformRedirection(n),r=`${e.operator}\0${e.target}`;t.has(r)||(t.add(r),s.push(e))}}else{n.push({name:e.text,nameType:"unknown",elementType:"CommandExpressionAst",args:[],text:e.text});for(const t of ensureArray(e.redirections))s.push(transformRedirection(t))}let r;const a=ensureArray(e.nestedCommands);a.length>0&&(r=a.map(transformCommandAst));const o={statementType:t,commands:n,redirections:s,text:e.text,nestedCommands:r};return e.securityPatterns&&(o.securityPatterns=e.securityPatterns),o}async function parsePowerShellCommandImpl(n){const a=Buffer.byteLength(n,"utf8");if(a>MAX_COMMAND_LENGTH)return t(`PowerShell parser: command too long (${a} bytes, max ${MAX_COMMAND_LENGTH})`),makeInvalidResult(n,`Command too long for parsing (${a} bytes). Maximum supported length is ${MAX_COMMAND_LENGTH} bytes.`,"CommandTooLong");const o=await s();if(!o)return makeInvalidResult(n,"PowerShell is not available","NoPowerShell");const i=function(e){return`$EncodedCommand = '${"undefined"!=typeof Buffer?Buffer.from(e,"utf8").toString("base64"):btoa((new TextEncoder).encode(e).reduce((e,t)=>e+String.fromCharCode(t),""))}'\n${PARSE_SCRIPT_BODY}`}(n),m=function(e){if("undefined"!=typeof Buffer)return Buffer.from(e,"utf16le").toString("base64");const t=[];for(let n=0;n<e.length;n++){const s=e.charCodeAt(n);t.push(255&s,s>>8&255)}return btoa(t.map(e=>String.fromCharCode(e)).join(""))}(i),c=["-NoProfile","-NonInteractive","-NoLogo","-EncodedCommand",m],l=function(){const e=process.env.CONTEXT_CODE_PWSH_PARSE_TIMEOUT_MS??process.env.CLAUDE_CODE_PWSH_PARSE_TIMEOUT_MS;if(e){const t=parseInt(e,10);if(!isNaN(t)&&t>0)return t}return 5e3}();let p="",d="",u=null,$=!1;for(let s=0;s<2;s++){try{const t=await e(o,c,{timeout:l,reject:!1});p=t.stdout,d=t.stderr,$=t.timedOut,u=t.failed?t.exitCode??1:0}catch(e){return t(`PowerShell parser: failed to spawn pwsh: ${e instanceof Error?e.message:e}`),makeInvalidResult(n,`Failed to spawn PowerShell: ${e instanceof Error?e.message:e}`,"PwshSpawnError")}if(!$)break;t(`PowerShell parser: pwsh timed out after ${l}ms (attempt ${s+1})`)}if($)return makeInvalidResult(n,`pwsh timed out after ${l}ms (2 attempts)`,"PwshTimeout");if(0!==u)return t(`PowerShell parser: pwsh exited with code ${u}, stderr: ${d}`),makeInvalidResult(n,`pwsh exited with code ${u}: ${d}`,"PwshError");const S=p.trim();if(!S)return t("PowerShell parser: empty stdout from pwsh"),makeInvalidResult(n,"No output from PowerShell parser","EmptyOutput");try{return function(e){const t={valid:e.valid,errors:ensureArray(e.errors),statements:ensureArray(e.statements).map(transformStatement),variables:ensureArray(e.variables),hasStopParsing:e.hasStopParsing,originalCommand:e.originalCommand},n=ensureArray(e.typeLiterals);return n.length>0&&(t.typeLiterals=n),e.hasUsingStatements&&(t.hasUsingStatements=!0),e.hasScriptRequirements&&(t.hasScriptRequirements=!0),t}(r(S))}catch{return t(`PowerShell parser: invalid JSON output: ${S.slice(0,200)}`),makeInvalidResult(n,"Invalid JSON from PowerShell parser","InvalidJson")}}const o=new Set(["PwshSpawnError","PwshError","PwshTimeout","EmptyOutput","InvalidJson"]),i=n(e=>{const t=parsePowerShellCommandImpl(e);return t.then(t=>{!t.valid&&o.has(t.errors[0]?.errorId??"")&&i.cache.delete(e)}),t},e=>e,256);export{i as parsePowerShellCommand};export const COMMON_ALIASES=Object.assign(Object.create(null),{ls:"Get-ChildItem",dir:"Get-ChildItem",gci:"Get-ChildItem",cat:"Get-Content",type:"Get-Content",gc:"Get-Content",cd:"Set-Location",sl:"Set-Location",chdir:"Set-Location",pushd:"Push-Location",popd:"Pop-Location",pwd:"Get-Location",gl:"Get-Location",gi:"Get-Item",gp:"Get-ItemProperty",ni:"New-Item",mkdir:"New-Item",md:"New-Item",ri:"Remove-Item",del:"Remove-Item",rd:"Remove-Item",rmdir:"Remove-Item",rm:"Remove-Item",erase:"Remove-Item",mi:"Move-Item",mv:"Move-Item",move:"Move-Item",ci:"Copy-Item",cp:"Copy-Item",copy:"Copy-Item",cpi:"Copy-Item",si:"Set-Item",rni:"Rename-Item",ren:"Rename-Item",ps:"Get-Process",gps:"Get-Process",kill:"Stop-Process",spps:"Stop-Process",start:"Start-Process",saps:"Start-Process",sajb:"Start-Job",ipmo:"Import-Module",echo:"Write-Output",write:"Write-Output",sleep:"Start-Sleep",help:"Get-Help",man:"Get-Help",gcm:"Get-Command",gsv:"Get-Service",gv:"Get-Variable",sv:"Set-Variable",h:"Get-History",history:"Get-History",iex:"Invoke-Expression",iwr:"Invoke-WebRequest",irm:"Invoke-RestMethod",icm:"Invoke-Command",ii:"Invoke-Item",nsn:"New-PSSession",etsn:"Enter-PSSession",exsn:"Exit-PSSession",gsn:"Get-PSSession",rsn:"Remove-PSSession",cls:"Clear-Host",clear:"Clear-Host",select:"Select-Object",where:"Where-Object",foreach:"ForEach-Object","%":"ForEach-Object","?":"Where-Object",measure:"Measure-Object",ft:"Format-Table",fl:"Format-List",fw:"Format-Wide",oh:"Out-Host",ogv:"Out-GridView",ac:"Add-Content",clc:"Clear-Content",tee:"Tee-Object",epcsv:"Export-Csv",sp:"Set-ItemProperty",rp:"Remove-ItemProperty",cli:"Clear-Item",epal:"Export-Alias",sls:"Select-String"});const m=new Set(["set-location","push-location","pop-location"]),c=new Set(["cd","sl","chdir","pushd","popd"]);export function getAllCommandNames(e){const t=[];for(const n of e.statements){for(const e of n.commands)t.push(e.name.toLowerCase());if(n.nestedCommands)for(const e of n.nestedCommands)t.push(e.name.toLowerCase())}return t}export function getAllCommands(e){const t=[];for(const n of e.statements){for(const e of n.commands)t.push(e);if(n.nestedCommands)for(const e of n.nestedCommands)t.push(e)}return t}export function getAllRedirections(e){const t=[];for(const n of e.statements){for(const e of n.redirections)t.push(e);if(n.nestedCommands)for(const e of n.nestedCommands)if(e.redirections)for(const n of e.redirections)t.push(n)}return t}export function getVariablesByScope(e,t){const n=t.toLowerCase()+":";return e.variables.filter(e=>e.path.toLowerCase().startsWith(n))}export function hasCommandNamed(e,t){const n=t.toLowerCase(),s=COMMON_ALIASES[n]?.toLowerCase();for(const t of getAllCommandNames(e)){if(t===n)return!0;const e=COMMON_ALIASES[t]?.toLowerCase();if(e===n)return!0;if(s&&t===s)return!0;if(e&&s&&e===s)return!0}return!1}export function hasDirectoryChange(e){for(const t of getAllCommandNames(e))if(m.has(t)||c.has(t))return!0;return!1}export function isSingleCommand(e){const t=e.statements[0];return 1===e.statements.length&&void 0!==t&&1===t.commands.length&&(!t.nestedCommands||0===t.nestedCommands.length)}export function commandHasArg(e,t){const n=t.toLowerCase();return e.args.some(e=>e.toLowerCase()===n)}export const PS_TOKENIZER_DASH_CHARS=new Set(["-","–","—","―"]);export function isPowerShellParameter(e,t){return void 0!==t?"Parameter"===t:e.length>0&&PS_TOKENIZER_DASH_CHARS.has(e[0])}export function commandHasArgAbbreviation(e,t,n){const s=t.toLowerCase(),r=n.toLowerCase();return e.args.some(e=>{const t=e.indexOf(":",1),n=(t>0?e.slice(0,t):e).replace(/`/g,"").toLowerCase();return n.startsWith(r)&&s.startsWith(n)&&n.length<=s.length})}export function getPipelineSegments(e){return e.statements}export function isNullRedirectionTarget(e){const t=e.trim().toLowerCase();return"$null"===t||"${null}"===t}export function getFileRedirections(e){return getAllRedirections(e).filter(e=>!e.isMerging&&!isNullRedirectionTarget(e.target))}export function deriveSecurityFlags(e){const t={hasSubExpressions:!1,hasScriptBlocks:!1,hasSplatting:!1,hasExpandableStrings:!1,hasMemberInvocations:!1,hasAssignments:!1,hasStopParsing:e.hasStopParsing};function checkElements(e){if(e.elementTypes)for(const n of e.elementTypes)switch(n){case"ScriptBlock":t.hasScriptBlocks=!0;break;case"SubExpression":t.hasSubExpressions=!0;break;case"ExpandableString":t.hasExpandableStrings=!0;break;case"MemberInvocation":t.hasMemberInvocations=!0}}for(const n of e.statements){"AssignmentStatementAst"===n.statementType&&(t.hasAssignments=!0);for(const e of n.commands)checkElements(e);if(n.nestedCommands)for(const e of n.nestedCommands)checkElements(e);n.securityPatterns&&(n.securityPatterns.hasMemberInvocations&&(t.hasMemberInvocations=!0),n.securityPatterns.hasSubExpressions&&(t.hasSubExpressions=!0),n.securityPatterns.hasExpandableStrings&&(t.hasExpandableStrings=!0),n.securityPatterns.hasScriptBlocks&&(t.hasScriptBlocks=!0))}for(const n of e.variables)if(n.isSplatted){t.hasSplatting=!0;break}return t}
@@ -1 +1 @@
1
- import{jsx as s,Fragment as e,jsxs as o}from"react/jsx-runtime";import{createRequire as r}from"module";const t=r(import.meta.url);import{randomUUID as a}from"crypto";import{BashModeProgress as l}from"src/components/BashModeProgress.js";import{BashTool as n}from"src/tools/BashTool/BashTool.js";import{logEvent as i}from"../../services/analytics/index.js";import{errorMessage as m,ShellError as d}from"../errors.js";import{createSyntheticUserCaveatMessage as u,createUserInterruptionMessage as c,createUserMessage as h,prepareUserContent as p}from"../messages.js";import{resolveDefaultShell as b}from"../shell/resolveDefaultShell.js";import{isPowerShellToolEnabled as g}from"../shell/shellToolUtils.js";import{processToolResultBlock as f}from"../toolResultStorage.js";import{escapeXml as j}from"../xml.js";export async function processBashCommand(r,v,S,y,w){const x=g()&&"powershell"===b();i("tengu_input_bash",{powershell:x});const T=h({content:p({inputString:`<bash-input>${r}</bash-input>`,precedingInputBlocks:v})});let B;w({jsx:s(l,{input:r,progress:null,verbose:y.options.verbose}),shouldHidePromptInput:!1});try{const i={...y,setToolJSX:s=>{B=s?.jsx}},onProgress=t=>{w({jsx:o(e,{children:[s(l,{input:r,progress:t.data,verbose:y.options.verbose}),B]}),shouldHidePromptInput:!1,showSpinner:!1})};let m=null;x&&(m=t("src/tools/PowerShellTool/PowerShellTool.js").PowerShellTool);const d=m??n,c=(m?await m.call({command:r,dangerouslyDisableSandbox:!0},i,void 0,void 0,onProgress):await n.call({command:r,dangerouslyDisableSandbox:!0},i,void 0,void 0,onProgress)).data;if(!c)throw new Error("No result received from shell command");const p=c.stderr,b=await f(d,{...c,stderr:""},a()),g="string"==typeof b.content?b.content:j(c.stdout);return{messages:[u(),T,...S,h({content:`<bash-stdout>${g}</bash-stdout><bash-stderr>${j(p)}</bash-stderr>`})],shouldQuery:!1}}catch(s){return s instanceof d?s.interrupted?{messages:[u(),T,c({toolUse:!1}),...S],shouldQuery:!1}:{messages:[u(),T,...S,h({content:`<bash-stdout>${j(s.stdout)}</bash-stdout><bash-stderr>${j(s.stderr)}</bash-stderr>`})],shouldQuery:!1}:{messages:[u(),T,...S,h({content:`<bash-stderr>Command failed: ${j(m(s))}</bash-stderr>`})],shouldQuery:!1}}finally{w(null)}}
1
+ import{jsx as o,Fragment as s,jsxs as t}from"react/jsx-runtime";import{createRequire as e}from"module";const r=e(import.meta.url);import{randomUUID as l}from"crypto";import{BashModeProgress as n}from"../../components/BashModeProgress.js";import{BashTool as a}from"../../tools/BashTool/BashTool.js";import{logEvent as i}from"../../services/analytics/index.js";import{errorMessage as m,ShellError as d}from"../errors.js";import{createSyntheticUserCaveatMessage as u,createUserInterruptionMessage as p,createUserMessage as h,prepareUserContent as c}from"../messages.js";import{resolveDefaultShell as b}from"../shell/resolveDefaultShell.js";import{isPowerShellToolEnabled as f}from"../shell/shellToolUtils.js";import{processToolResultBlock as g}from"../toolResultStorage.js";import{escapeXml as j}from"../xml.js";export async function processBashCommand(e,y,v,w,x){const S=f()&&"powershell"===b();i("tengu_input_bash",{powershell:S});const T=h({content:c({inputString:`<bash-input>${e}</bash-input>`,precedingInputBlocks:y})});let P;x({jsx:o(n,{input:e,progress:null,verbose:w.options.verbose}),shouldHidePromptInput:!1});try{const i={...w,setToolJSX:o=>{P=o?.jsx}},onProgress=r=>{x({jsx:t(s,{children:[o(n,{input:e,progress:r.data,verbose:w.options.verbose}),P]}),shouldHidePromptInput:!1,showSpinner:!1})};let m=null;S&&(m=r("../../tools/PowerShellTool/PowerShellTool.js").PowerShellTool);const d=m??a,p=(m?await m.call({command:e,dangerouslyDisableSandbox:!0},i,void 0,void 0,onProgress):await a.call({command:e,dangerouslyDisableSandbox:!0},i,void 0,void 0,onProgress)).data;if(!p)throw new Error("No result received from shell command");const c=p.stderr,b=await g(d,{...p,stderr:""},l()),f="string"==typeof b.content?b.content:j(p.stdout);return{messages:[u(),T,...v,h({content:`<bash-stdout>${f}</bash-stdout><bash-stderr>${j(c)}</bash-stderr>`})],shouldQuery:!1}}catch(o){return o instanceof d?o.interrupted?{messages:[u(),T,p({toolUse:!1}),...v],shouldQuery:!1}:{messages:[u(),T,...v,h({content:`<bash-stdout>${j(o.stdout)}</bash-stdout><bash-stderr>${j(o.stderr)}</bash-stderr>`})],shouldQuery:!1}:{messages:[u(),T,...v,h({content:`<bash-stderr>Command failed: ${j(m(o))}</bash-stderr>`})],shouldQuery:!1}}finally{x(null)}}
@@ -1 +1 @@
1
- import{feature as e}from"bun:bundle";import{randomUUID as t}from"crypto";import{setPromptId as o}from"src/bootstrap/state.js";import{builtInCommandNames as s,findCommand as n,getCommand as a,getCommandName as r,hasCommand as m}from"src/commands.js";import{NO_CONTENT_MESSAGE as i}from"src/constants/messages.js";import{addInvokedSkill as l,getSessionId as p}from"../../bootstrap/state.js";import{COMMAND_MESSAGE_TAG as c,COMMAND_NAME_TAG as u}from"../../constants/xml.js";import{logEvent as d}from"../../services/analytics/index.js";import{getDumpPromptsPath as g}from"../../services/api/dumpPrompts.js";import{buildPostCompactMessages as f}from"../../services/compact/compact.js";import{resetMicrocompactState as h}from"../../services/compact/microCompact.js";import{runAgent as y}from"../../tools/AgentTool/runAgent.js";import{renderToolUseProgressMessage as I}from"../../tools/AgentTool/UI.js";import{createAbortController as k}from"../abortController.js";import{getAgentContext as T}from"../agentContext.js";import{createAttachmentMessage as C,getAttachmentMessages as _}from"../attachments.js";import{logForDebugging as S}from"../debug.js";import{isEnvTruthy as j}from"../envUtils.js";import{AbortError as M,MalformedCommandError as x}from"../errors.js";import{getDisplayPath as $}from"../file.js";import{extractResultText as v,prepareForkedCommandContext as w}from"../forkedAgent.js";import{getFsImplementation as O}from"../fsOperations.js";import{isFullscreenEnvEnabled as A}from"../fullscreen.js";import{toArray as b}from"../generators.js";import{registerSkillHooks as P}from"../hooks/registerSkillHooks.js";import{logError as U}from"../log.js";import{enqueuePendingNotification as D}from"../messageQueueManager.js";import{createCommandInputMessage as E,createSyntheticUserCaveatMessage as Q,createSystemMessage as N,createUserInterruptionMessage as L,createUserMessage as R,formatCommandInputTags as F,isCompactBoundaryMessage as B,isSystemLocalCommandMessage as W,normalizeMessages as H,prepareUserContent as G}from"../messages.js";import{parseToolListFromCLI as X}from"../permissions/permissionSetup.js";import{hasPermissionsToUseTool as q}from"../permissions/permissions.js";import{isOfficialMarketplaceName as J,parsePluginIdentifier as K}from"../plugins/pluginIdentifier.js";import{isRestrictedToPluginOnly as z,isSourceAdminTrusted as Z}from"../settings/pluginOnlyPolicy.js";import{parseSlashCommand as V}from"../slashCommandParsing.js";import{sleep as Y}from"../sleep.js";import{recordSkillUsage as ee}from"../suggestions/skillUsageTracking.js";import{logOTelEvent as te,redactIfDisabled as oe}from"../telemetry/events.js";import{buildPluginCommandTelemetryFields as se}from"../telemetry/pluginTelemetry.js";import{getAssistantMessageContentLength as ne}from"../tokens.js";import{createAgentId as ae}from"../uuid.js";import{getWorkload as re}from"../workloadContext.js";export function looksLikeCommand(e){return!/[^a-zA-Z0-9:\-_]/.test(e)}export async function processSlashCommand(n,l,p,c,u,g,T,C,_){const j=V(n);if(!j){d("tengu_input_slash_missing",{});const e="Commands are in the form `/command [args]`";return{messages:[Q(),...c,R({content:G({inputString:e,precedingInputBlocks:l})})],shouldQuery:!1,resultText:e}}const{commandName:$,args:b,isMcp:P}=j,F=P?"mcp":s().has($)?$:"custom";if(!m($,u.options.commands)){let e=!1;try{await O().stat(`/${$}`),e=!0}catch{}if(looksLikeCommand($)&&!e){d("tengu_input_slash_invalid",{input:$});const e=`Unknown skill: ${$}`;return{messages:[Q(),...c,R({content:G({inputString:e,precedingInputBlocks:l})}),...b?[N(`Argumentos de habilidad desconocida: ${b}`,"error")]:[]],shouldQuery:!1,resultText:e}}const s=t();return o(s),d("tengu_input_prompt",{}),te("user_prompt",{prompt_length:String(n.length),prompt:oe(n),"prompt.id":s}),{messages:[R({content:G({inputString:n,precedingInputBlocks:l}),uuid:T}),...c],shouldQuery:!0}}const{messages:X,shouldQuery:z,allowedTools:Z,model:me,effort:ie,command:le,resultText:pe,nextInput:ce,submitNextInput:ue,jumpToMessageId:de}=await async function(o,s,n,m,l,p,c,u,g){const T=a(o,m.options.commands);if("prompt"===T.type&&!1!==T.userInvocable&&ee(o),!1===T.userInvocable)return{messages:[R({content:G({inputString:`/${o}`,precedingInputBlocks:l})}),R({content:`This skill can only be invoked by Claude, not directly by users. Ask Claude to use the "${o}" skill for you.`})],shouldQuery:!1,command:T};try{switch(T.type){case"local-jsx":return new Promise(e=>{let t=!1;const o=setTimeout(()=>{t||(t=!0,n({jsx:null,shouldHidePromptInput:!1,clearLocalJSX:!0}),e({messages:[],shouldQuery:!1,command:T}))},3e4),onDone=(n,a)=>{if(t=!0,clearTimeout(o),"skip"===a?.display)return void e({messages:[],shouldQuery:!1,command:T,nextInput:a?.nextInput,submitNextInput:a?.submitNextInput,jumpToMessageId:a?.jumpToMessageId});const r=(a?.metaMessages??[]).map(e=>R({content:e,isMeta:!0})),m=A()&&"string"==typeof n&&n.endsWith(" dismissed");e({messages:"system"===a?.display?m?r:[E(formatCommandInput(T,s)),E(`<local-command-stdout>${n}</local-command-stdout>`),...r]:[R({content:G({inputString:formatCommandInput(T,s),precedingInputBlocks:l})}),R(n?{content:`<local-command-stdout>${n}</local-command-stdout>`}:{content:`<local-command-stdout>${i}</local-command-stdout>`}),...r],shouldQuery:a?.shouldQuery??!1,command:T,nextInput:a?.nextInput,submitNextInput:a?.submitNextInput,jumpToMessageId:a?.jumpToMessageId})};T.load().then(e=>e.call(onDone,{...m,canUseTool:u},s)).then(o=>{null!=o&&(m.options.isNonInteractiveSession?e({messages:[],shouldQuery:!1,command:T}):t||n({jsx:o,shouldHidePromptInput:!0,showSpinner:!1,isLocalJSXCommand:!0,isImmediate:!0===T.immediate}))}).catch(s=>{U(s),t||(t=!0,clearTimeout(o),n({jsx:null,shouldHidePromptInput:!1,clearLocalJSX:!0}),e({messages:[],shouldQuery:!1,command:T}))})});case"local":{const e=T.isSensitive&&s.trim()?"***":s,t=R({content:G({inputString:formatCommandInput(T,e),precedingInputBlocks:l})});try{const e=Q(),o=await T.load(),n=await o.call(s,m);if("skip"===n.type)return{messages:[],shouldQuery:!1,command:T};if("compact"===n.type){const o=[e,t,...n.displayText?[R({content:`<local-command-stdout>${n.displayText}</local-command-stdout>`,timestamp:new Date(Date.now()+100).toISOString()})]:[]],s={...n.compactionResult,messagesToKeep:[...n.compactionResult.messagesToKeep??[],...o]};return h(),{messages:f(s),shouldQuery:!1,command:T}}return{messages:[t,E(`<local-command-stdout>${n.value}</local-command-stdout>`)],shouldQuery:!1,command:T,resultText:n.value}}catch(e){return U(e),{messages:[t,E(`<local-command-stderr>${String(e)}</local-command-stderr>`)],shouldQuery:!1,command:T}}}case"prompt":try{return"fork"===T.context?await async function(o,s,n,a,m,i){const l=ae(),p=o.pluginInfo?K(o.pluginInfo.repository).marketplace:void 0;d("tengu_slash_command_forked",{command_name:o.name,invocation_trigger:"user-slash",...o.pluginInfo&&{_PROTO_plugin_name:o.pluginInfo.pluginManifest.name,...p&&{_PROTO_marketplace_name:p},...se(o.pluginInfo)}});const{skillContent:c,modifiedGetAppState:u,baseAgent:g,promptMessages:f}=await w(o,s,n),h=void 0!==o.effort?{...g,effort:o.effort}:g;if(S(`Executing forked slash command /${o.name} with agent ${h.agentType}`),e("KAIROS")&&(await n.getAppState()).kairosEnabled){const e=k(),t=r(o),s=re(),enqueueResult=e=>D({value:e,mode:"prompt",priority:"later",isMeta:!0,skipSlashCommands:!0,workload:s});return(async()=>{const s=Date.now()+1e4;for(;Date.now()<s&&n.getAppState().mcp.clients.some(e=>"pending"===e.type);)await Y(200);const a=n.options.refreshTools?.()??n.options.tools,r=[];for await(const t of y({agentDefinition:h,promptMessages:f,toolUseContext:{...n,getAppState:u,abortController:e},canUseTool:i,isAsync:!0,querySource:"agent:custom",model:o.model,availableTools:a,override:{agentId:l}}))r.push(t);const m=v(r,"Command completed");S(`Background forked command /${t} completed (agent ${l})`),enqueueResult(`<scheduled-task-result command="/${t}">\n${m}\n</scheduled-task-result>`)})().catch(e=>{U(e),enqueueResult(`<scheduled-task-result command="/${t}" status="failed">\n${e instanceof Error?e.message:String(e)}\n</scheduled-task-result>`)}),{messages:[],shouldQuery:!1,command:o}}const T=[],C=[],_=`forked-command-${o.name}`;let j=0;const createProgressMessage=e=>(j++,{type:"progress",data:{message:e,type:"agent_progress",prompt:c,agentId:l},parentToolUseID:_,toolUseID:`${_}-${j}`,timestamp:(new Date).toISOString(),uuid:t()}),updateProgress=()=>{m({jsx:I(C,{tools:n.options.tools,verbose:!1}),shouldHidePromptInput:!1,shouldContinueAnimation:!0,showSpinner:!0})};updateProgress();try{for await(const e of y({agentDefinition:h,promptMessages:f,toolUseContext:{...n,getAppState:u},canUseTool:i,isAsync:!1,querySource:"agent:custom",model:o.model,availableTools:n.options.tools})){T.push(e);const t=H([e]);if("assistant"===e.type){const o=ne(e);o>0&&n.setResponseLength(e=>e+o);const s=t[0];s&&"assistant"===s.type&&(C.push(createProgressMessage(e)),updateProgress())}if("user"===e.type){const e=t[0];e&&"user"===e.type&&(C.push(createProgressMessage(e)),updateProgress())}}}finally{m(null)}let M=v(T,"Command completed");return S(`Forked slash command /${o.name} completed with agent ${l}`),{messages:[R({content:G({inputString:`/${r(o)} ${s}`.trim(),precedingInputBlocks:a})}),R({content:`<local-command-stdout>\n${M}\n</local-command-stdout>`})],shouldQuery:!1,command:o,resultText:M}}(T,s,m,l,n,u??q):await getMessagesForPromptSlashCommand(T,s,m,l,p,g)}catch(e){return e instanceof M?{messages:[R({content:G({inputString:formatCommandInput(T,s),precedingInputBlocks:l})}),L({toolUse:!1})],shouldQuery:!1,command:T}:{messages:[R({content:G({inputString:formatCommandInput(T,s),precedingInputBlocks:l})}),R({content:`<local-command-stderr>${String(e)}</local-command-stderr>`})],shouldQuery:!1,command:T}}}}catch(e){if(e instanceof x)return{messages:[R({content:G({inputString:e.message,precedingInputBlocks:l})})],shouldQuery:!1,command:T};throw e}}($,b,g,u,l,p,0,_,T);if(0===X.length){const e={input:F};if("prompt"===le.type&&le.pluginInfo){const{pluginManifest:t,repository:o}=le.pluginInfo,{marketplace:s}=K(o),n=J(s);e._PROTO_plugin_name=t.name,s&&(e._PROTO_marketplace_name=s),e.plugin_repository=n?o:"third-party",e.plugin_name=n?t.name:"third-party",n&&t.version&&(e.plugin_version=t.version),Object.assign(e,se(le.pluginInfo))}return d("tengu_input_command",{...e,invocation_trigger:"user-slash"}),{messages:[],shouldQuery:!1,model:me,nextInput:ce,submitNextInput:ue,jumpToMessageId:de}}if(2===X.length&&"user"===X[1].type&&"string"==typeof X[1].message.content&&X[1].message.content.startsWith("Unknown command:"))return n.startsWith("/var")||n.startsWith("/tmp")||n.startsWith("/private")||d("tengu_input_slash_invalid",{input:$}),{messages:[Q(),...X],shouldQuery:z,allowedTools:Z,model:me};const ge={input:F};if("prompt"===le.type&&le.pluginInfo){const{pluginManifest:e,repository:t}=le.pluginInfo,{marketplace:o}=K(t),s=J(o);ge._PROTO_plugin_name=e.name,o&&(ge._PROTO_marketplace_name=o),ge.plugin_repository=s?t:"third-party",ge.plugin_name=s?e.name:"third-party",s&&e.version&&(ge.plugin_version=e.version),Object.assign(ge,se(le.pluginInfo))}d("tengu_input_command",{...ge,invocation_trigger:"user-slash"});const fe=X.length>0&&X[0]&&B(X[0]);return{messages:z||X.every(W)||fe?X:[Q(),...X],shouldQuery:z,allowedTools:Z,model:me,effort:ie,resultText:pe,nextInput:ce,submitNextInput:ue,jumpToMessageId:de}}function formatCommandInput(e,t){return F(r(e),t)}export function formatSkillLoadingMetadata(e,t="loading"){return[`<${c}>${e}</${c}>`,`<${u}>${e}</${u}>`,"<skill-format>true</skill-format>"].join("\n")}function formatSlashCommandLoadingMetadata(e,t){return[`<${c}>${e}</${c}>`,`<${u}>/${e}</${u}>`,t?`<command-args>${t}</command-args>`:null].filter(Boolean).join("\n")}function formatCommandLoadingMetadata(e,t){return!1!==e.userInvocable?formatSlashCommandLoadingMetadata(e.name,t):"skills"===e.loadedFrom||"plugin"===e.loadedFrom||"mcp"===e.loadedFrom?formatSkillLoadingMetadata(e.name,e.progressMessage):formatSlashCommandLoadingMetadata(e.name,t)}export async function processPromptSlashCommand(e,t,o,s,a=[]){const r=n(e,o);if(!r)throw new x(`Unknown command: ${e}`);if("prompt"!==r.type)throw new Error(`Unexpected ${r.type} command. Expected 'prompt' command. Use /${e} directly in the main conversation.`);return getMessagesForPromptSlashCommand(r,t,s,[],a)}async function getMessagesForPromptSlashCommand(t,o,s,n=[],a=[],r){if(e("COORDINATOR_MODE")&&(j(process.env.CONTEXT_CODE_COORDINATOR_MODE)||j(process.env.CLAUDE_CODE_COORDINATOR_MODE))&&!s.agentId){const e=formatCommandLoadingMetadata(t,o),s=[`Skill "/${t.name}" is available for workers.`];t.description&&s.push(`Description: ${t.description}`),t.whenToUse&&s.push(`When to use: ${t.whenToUse}`);const n=t.allowedTools??[];n.length>0&&s.push(`This skill grants workers additional tool permissions: ${n.join(", ")}`),s.push(`\nInstruct a worker to use this skill by including "Use the /${t.name} skill" in your Agent prompt. The worker has access to the Skill tool and will receive the skill's content and permissions when it invokes it.`);const a=[{type:"text",text:s.join("\n")}];return{messages:[R({content:e,uuid:r}),R({content:a,isMeta:!0})],shouldQuery:!0,model:t.model,effort:t.effort,command:t}}const m=await t.getPromptForCommand(o,s),i=!z("hooks")||Z(t.source);if(t.hooks&&i){const e=p();P(s.setAppState,e,t.hooks,t.name,"prompt"===t.type?t.skillRoot:void 0)}const c=t.source?`${t.source}:${t.name}`:t.name,u=m.filter(e=>"text"===e.type).map(e=>e.text).join("\n\n");l(t.name,c,u,T()?.agentId??null);const d=formatCommandLoadingMetadata(t,o),g=X(t.allowedTools??[]),f=a.length>0||n.length>0?[...a,...n,...m]:m,h=await b(_(m.filter(e=>"text"===e.type).map(e=>e.text).join(" "),s,null,[],s.messages,"repl_main_thread",{skipSkillDiscovery:!0}));return{messages:[R({content:d,uuid:r}),R({content:f,isMeta:!0}),...h,C({type:"command_permissions",allowedTools:g,model:t.model})],shouldQuery:!0,allowedTools:g,model:t.model,effort:t.effort,command:t}}
1
+ import{feature as t}from"../../recovery/bunBundleShim.js";import{randomUUID as o}from"crypto";import{setPromptId as e}from"../../bootstrap/state.js";import{builtInCommandNames as s,findCommand as n,getCommand as a,getCommandName as r,hasCommand as m}from"../../commands.js";import{NO_CONTENT_MESSAGE as i}from"../../constants/messages.js";import{addInvokedSkill as l,getSessionId as p}from"../../bootstrap/state.js";import{COMMAND_MESSAGE_TAG as u,COMMAND_NAME_TAG as c}from"../../constants/xml.js";import{logEvent as d}from"../../services/analytics/index.js";import{getDumpPromptsPath as g}from"../../services/api/dumpPrompts.js";import{buildPostCompactMessages as f}from"../../services/compact/compact.js";import{resetMicrocompactState as h}from"../../services/compact/microCompact.js";import{runAgent as y}from"../../tools/AgentTool/runAgent.js";import{renderToolUseProgressMessage as k}from"../../tools/AgentTool/UI.js";import{createAbortController as I}from"../abortController.js";import{getAgentContext as _}from"../agentContext.js";import{createAttachmentMessage as j,getAttachmentMessages as T}from"../attachments.js";import{logForDebugging as S}from"../debug.js";import{isEnvTruthy as $}from"../envUtils.js";import{AbortError as w,MalformedCommandError as x}from"../errors.js";import{getDisplayPath as v}from"../file.js";import{extractResultText as C,prepareForkedCommandContext as M}from"../forkedAgent.js";import{getFsImplementation as O}from"../fsOperations.js";import{isFullscreenEnvEnabled as b}from"../fullscreen.js";import{toArray as Q}from"../generators.js";import{registerSkillHooks as A}from"../hooks/registerSkillHooks.js";import{logError as D}from"../log.js";import{enqueuePendingNotification as U}from"../messageQueueManager.js";import{createCommandInputMessage as P,createSyntheticUserCaveatMessage as R,createSystemMessage as L,createUserInterruptionMessage as B,createUserMessage as N,formatCommandInputTags as E,isCompactBoundaryMessage as F,isSystemLocalCommandMessage as W,normalizeMessages as H,prepareUserContent as X}from"../messages.js";import{parseToolListFromCLI as J}from"../permissions/permissionSetup.js";import{hasPermissionsToUseTool as K}from"../permissions/permissions.js";import{isOfficialMarketplaceName as q,parsePluginIdentifier as z}from"../plugins/pluginIdentifier.js";import{isRestrictedToPluginOnly as G,isSourceAdminTrusted as Z}from"../settings/pluginOnlyPolicy.js";import{parseSlashCommand as V}from"../slashCommandParsing.js";import{sleep as Y}from"../sleep.js";import{recordSkillUsage as tt}from"../suggestions/skillUsageTracking.js";import{logOTelEvent as ot,redactIfDisabled as et}from"../telemetry/events.js";import{buildPluginCommandTelemetryFields as st}from"../telemetry/pluginTelemetry.js";import{getAssistantMessageContentLength as nt}from"../tokens.js";import{createAgentId as at}from"../uuid.js";import{getWorkload as rt}from"../workloadContext.js";export function looksLikeCommand(t){return!/[^a-zA-Z0-9:\-_]/.test(t)}export async function processSlashCommand(n,l,p,u,c,g,_,j,T){const $=V(n);if(!$){d("tengu_input_slash_missing",{});const t="Commands are in the form `/command [args]`";return{messages:[R(),...u,N({content:X({inputString:t,precedingInputBlocks:l})})],shouldQuery:!1,resultText:t}}const{commandName:v,args:Q,isMcp:A}=$,E=A?"mcp":s().has(v)?v:"custom";if(!m(v,c.options.commands)){let t=!1;try{await O().stat(`/${v}`),t=!0}catch{}if(looksLikeCommand(v)&&!t){d("tengu_input_slash_invalid",{input:v});const t=`Unknown skill: ${v}`;return{messages:[R(),...u,N({content:X({inputString:t,precedingInputBlocks:l})}),...Q?[L(`Argumentos de habilidad desconocida: ${Q}`,"error")]:[]],shouldQuery:!1,resultText:t}}const s=o();return e(s),d("tengu_input_prompt",{}),ot("user_prompt",{prompt_length:String(n.length),prompt:et(n),"prompt.id":s}),{messages:[N({content:X({inputString:n,precedingInputBlocks:l}),uuid:_}),...u],shouldQuery:!0}}const{messages:J,shouldQuery:G,allowedTools:Z,model:mt,effort:it,command:lt,resultText:pt,nextInput:ut,submitNextInput:ct,jumpToMessageId:dt}=await async function(e,s,n,m,l,p,u,c,g){const _=a(e,m.options.commands);"prompt"===_.type&&!1!==_.userInvocable&&tt(e);if(!1===_.userInvocable)return{messages:[N({content:X({inputString:`/${e}`,precedingInputBlocks:l})}),N({content:`This skill can only be invoked by Claude, not directly by users. Ask Claude to use the "${e}" skill for you.`})],shouldQuery:!1,command:_};try{switch(_.type){case"local-jsx":return new Promise(t=>{let o=!1;const e=setTimeout(()=>{o||(o=!0,n({jsx:null,shouldHidePromptInput:!1,clearLocalJSX:!0}),t({messages:[],shouldQuery:!1,command:_}))},3e4),onDone=(n,a)=>{if(o=!0,clearTimeout(e),"skip"===a?.display)return void t({messages:[],shouldQuery:!1,command:_,nextInput:a?.nextInput,submitNextInput:a?.submitNextInput,jumpToMessageId:a?.jumpToMessageId});const r=(a?.metaMessages??[]).map(t=>N({content:t,isMeta:!0})),m=b()&&"string"==typeof n&&n.endsWith(" dismissed");t({messages:"system"===a?.display?m?r:[P(formatCommandInput(_,s)),P(`<local-command-stdout>${n}</local-command-stdout>`),...r]:[N({content:X({inputString:formatCommandInput(_,s),precedingInputBlocks:l})}),N(n?{content:`<local-command-stdout>${n}</local-command-stdout>`}:{content:`<local-command-stdout>${i}</local-command-stdout>`}),...r],shouldQuery:a?.shouldQuery??!1,command:_,nextInput:a?.nextInput,submitNextInput:a?.submitNextInput,jumpToMessageId:a?.jumpToMessageId})};_.load().then(t=>t.call(onDone,{...m,canUseTool:c},s)).then(e=>{null!=e&&(m.options.isNonInteractiveSession?t({messages:[],shouldQuery:!1,command:_}):o||n({jsx:e,shouldHidePromptInput:!0,showSpinner:!1,isLocalJSXCommand:!0,isImmediate:!0===_.immediate}))}).catch(s=>{D(s),o||(o=!0,clearTimeout(e),n({jsx:null,shouldHidePromptInput:!1,clearLocalJSX:!0}),t({messages:[],shouldQuery:!1,command:_}))})});case"local":{const t=_.isSensitive&&s.trim()?"***":s,o=N({content:X({inputString:formatCommandInput(_,t),precedingInputBlocks:l})});try{const t=R(),e=await _.load(),n=await e.call(s,m);if("skip"===n.type)return{messages:[],shouldQuery:!1,command:_};if("compact"===n.type){const e=[t,o,...n.displayText?[N({content:`<local-command-stdout>${n.displayText}</local-command-stdout>`,timestamp:new Date(Date.now()+100).toISOString()})]:[]],s={...n.compactionResult,messagesToKeep:[...n.compactionResult.messagesToKeep??[],...e]};return h(),{messages:f(s),shouldQuery:!1,command:_}}return{messages:[o,P(`<local-command-stdout>${n.value}</local-command-stdout>`)],shouldQuery:!1,command:_,resultText:n.value}}catch(t){return D(t),{messages:[o,P(`<local-command-stderr>${String(t)}</local-command-stderr>`)],shouldQuery:!1,command:_}}}case"prompt":try{return"fork"===_.context?await async function(e,s,n,a,m,i){const l=at(),p=e.pluginInfo?z(e.pluginInfo.repository).marketplace:void 0;d("tengu_slash_command_forked",{command_name:e.name,invocation_trigger:"user-slash",...e.pluginInfo&&{_PROTO_plugin_name:e.pluginInfo.pluginManifest.name,...p&&{_PROTO_marketplace_name:p},...st(e.pluginInfo)}});const{skillContent:u,modifiedGetAppState:c,baseAgent:g,promptMessages:f}=await M(e,s,n),h=void 0!==e.effort?{...g,effort:e.effort}:g;if(S(`Executing forked slash command /${e.name} with agent ${h.agentType}`),t("KAIROS")&&(await n.getAppState()).kairosEnabled){const t=I(),o=r(e),s=rt(),enqueueResult=t=>U({value:t,mode:"prompt",priority:"later",isMeta:!0,skipSlashCommands:!0,workload:s});return(async()=>{const s=Date.now()+1e4;for(;Date.now()<s&&n.getAppState().mcp.clients.some(t=>"pending"===t.type);)await Y(200);const a=n.options.refreshTools?.()??n.options.tools,r=[];for await(const o of y({agentDefinition:h,promptMessages:f,toolUseContext:{...n,getAppState:c,abortController:t},canUseTool:i,isAsync:!0,querySource:"agent:custom",model:e.model,availableTools:a,override:{agentId:l}}))r.push(o);const m=C(r,"Command completed");S(`Background forked command /${o} completed (agent ${l})`),enqueueResult(`<scheduled-task-result command="/${o}">\n${m}\n</scheduled-task-result>`)})().catch(t=>{D(t),enqueueResult(`<scheduled-task-result command="/${o}" status="failed">\n${t instanceof Error?t.message:String(t)}\n</scheduled-task-result>`)}),{messages:[],shouldQuery:!1,command:e}}const _=[],j=[],T=`forked-command-${e.name}`;let $=0;const createProgressMessage=t=>($++,{type:"progress",data:{message:t,type:"agent_progress",prompt:u,agentId:l},parentToolUseID:T,toolUseID:`${T}-${$}`,timestamp:(new Date).toISOString(),uuid:o()}),updateProgress=()=>{m({jsx:k(j,{tools:n.options.tools,verbose:!1}),shouldHidePromptInput:!1,shouldContinueAnimation:!0,showSpinner:!0})};updateProgress();try{for await(const t of y({agentDefinition:h,promptMessages:f,toolUseContext:{...n,getAppState:c},canUseTool:i,isAsync:!1,querySource:"agent:custom",model:e.model,availableTools:n.options.tools})){_.push(t);const o=H([t]);if("assistant"===t.type){const e=nt(t);e>0&&n.setResponseLength(t=>t+e);const s=o[0];s&&"assistant"===s.type&&(j.push(createProgressMessage(t)),updateProgress())}if("user"===t.type){const t=o[0];t&&"user"===t.type&&(j.push(createProgressMessage(t)),updateProgress())}}}finally{m(null)}let w=C(_,"Command completed");return S(`Forked slash command /${e.name} completed with agent ${l}`),{messages:[N({content:X({inputString:`/${r(e)} ${s}`.trim(),precedingInputBlocks:a})}),N({content:`<local-command-stdout>\n${w}\n</local-command-stdout>`})],shouldQuery:!1,command:e,resultText:w}}(_,s,m,l,n,c??K):await getMessagesForPromptSlashCommand(_,s,m,l,p,g)}catch(t){return t instanceof w?{messages:[N({content:X({inputString:formatCommandInput(_,s),precedingInputBlocks:l})}),B({toolUse:!1})],shouldQuery:!1,command:_}:{messages:[N({content:X({inputString:formatCommandInput(_,s),precedingInputBlocks:l})}),N({content:`<local-command-stderr>${String(t)}</local-command-stderr>`})],shouldQuery:!1,command:_}}}}catch(t){if(t instanceof x)return{messages:[N({content:X({inputString:t.message,precedingInputBlocks:l})})],shouldQuery:!1,command:_};throw t}}(v,Q,g,c,l,p,0,T,_);if(0===J.length){const t={input:E};if("prompt"===lt.type&&lt.pluginInfo){const{pluginManifest:o,repository:e}=lt.pluginInfo,{marketplace:s}=z(e),n=q(s);t._PROTO_plugin_name=o.name,s&&(t._PROTO_marketplace_name=s),t.plugin_repository=n?e:"third-party",t.plugin_name=n?o.name:"third-party",n&&o.version&&(t.plugin_version=o.version),Object.assign(t,st(lt.pluginInfo))}return d("tengu_input_command",{...t,invocation_trigger:"user-slash"}),{messages:[],shouldQuery:!1,model:mt,nextInput:ut,submitNextInput:ct,jumpToMessageId:dt}}if(2===J.length&&"user"===J[1].type&&"string"==typeof J[1].message.content&&J[1].message.content.startsWith("Unknown command:")){return n.startsWith("/var")||n.startsWith("/tmp")||n.startsWith("/private")||d("tengu_input_slash_invalid",{input:v}),{messages:[R(),...J],shouldQuery:G,allowedTools:Z,model:mt}}const gt={input:E};if("prompt"===lt.type&&lt.pluginInfo){const{pluginManifest:t,repository:o}=lt.pluginInfo,{marketplace:e}=z(o),s=q(e);gt._PROTO_plugin_name=t.name,e&&(gt._PROTO_marketplace_name=e),gt.plugin_repository=s?o:"third-party",gt.plugin_name=s?t.name:"third-party",s&&t.version&&(gt.plugin_version=t.version),Object.assign(gt,st(lt.pluginInfo))}d("tengu_input_command",{...gt,invocation_trigger:"user-slash"});const ft=J.length>0&&J[0]&&F(J[0]);return{messages:G||J.every(W)||ft?J:[R(),...J],shouldQuery:G,allowedTools:Z,model:mt,effort:it,resultText:pt,nextInput:ut,submitNextInput:ct,jumpToMessageId:dt}}function formatCommandInput(t,o){return E(r(t),o)}export function formatSkillLoadingMetadata(t,o="loading"){return[`<${u}>${t}</${u}>`,`<${c}>${t}</${c}>`,"<skill-format>true</skill-format>"].join("\n")}function formatSlashCommandLoadingMetadata(t,o){return[`<${u}>${t}</${u}>`,`<${c}>/${t}</${c}>`,o?`<command-args>${o}</command-args>`:null].filter(Boolean).join("\n")}function formatCommandLoadingMetadata(t,o){return!1!==t.userInvocable?formatSlashCommandLoadingMetadata(t.name,o):"skills"===t.loadedFrom||"plugin"===t.loadedFrom||"mcp"===t.loadedFrom?formatSkillLoadingMetadata(t.name,t.progressMessage):formatSlashCommandLoadingMetadata(t.name,o)}export async function processPromptSlashCommand(t,o,e,s,a=[]){const r=n(t,e);if(!r)throw new x(`Unknown command: ${t}`);if("prompt"!==r.type)throw new Error(`Unexpected ${r.type} command. Expected 'prompt' command. Use /${t} directly in the main conversation.`);return getMessagesForPromptSlashCommand(r,o,s,[],a)}async function getMessagesForPromptSlashCommand(o,e,s,n=[],a=[],r){if(t("COORDINATOR_MODE")&&($(process.env.CONTEXT_CODE_COORDINATOR_MODE)||$(process.env.CLAUDE_CODE_COORDINATOR_MODE))&&!s.agentId){const t=formatCommandLoadingMetadata(o,e),s=[`Skill "/${o.name}" is available for workers.`];o.description&&s.push(`Description: ${o.description}`),o.whenToUse&&s.push(`When to use: ${o.whenToUse}`);const n=o.allowedTools??[];n.length>0&&s.push(`This skill grants workers additional tool permissions: ${n.join(", ")}`),s.push(`\nInstruct a worker to use this skill by including "Use the /${o.name} skill" in your Agent prompt. The worker has access to the Skill tool and will receive the skill's content and permissions when it invokes it.`);const a=[{type:"text",text:s.join("\n")}];return{messages:[N({content:t,uuid:r}),N({content:a,isMeta:!0})],shouldQuery:!0,model:o.model,effort:o.effort,command:o}}const m=await o.getPromptForCommand(e,s),i=!G("hooks")||Z(o.source);if(o.hooks&&i){const t=p();A(s.setAppState,t,o.hooks,o.name,"prompt"===o.type?o.skillRoot:void 0)}const u=o.source?`${o.source}:${o.name}`:o.name,c=m.filter(t=>"text"===t.type).map(t=>t.text).join("\n\n");l(o.name,u,c,_()?.agentId??null);const d=formatCommandLoadingMetadata(o,e),g=J(o.allowedTools??[]),f=a.length>0||n.length>0?[...a,...n,...m]:m,h=await Q(T(m.filter(t=>"text"===t.type).map(t=>t.text).join(" "),s,null,[],s.messages,"repl_main_thread",{skipSkillDiscovery:!0}));return{messages:[N({content:d,uuid:r}),N({content:f,isMeta:!0}),...h,j({type:"command_permissions",allowedTools:g,model:o.model})],shouldQuery:!0,allowedTools:g,model:o.model,effort:o.effort,command:o}}
@@ -1 +1 @@
1
- import{randomUUID as t}from"crypto";import{setPromptId as e}from"src/bootstrap/state.js";import{logEvent as s}from"../../services/analytics/index.js";import{createUserMessage as o}from"../messages.js";import{logOTelEvent as r,redactIfDisabled as i}from"../telemetry/events.js";import{startInteractionSpan as n}from"../telemetry/sessionTracing.js";import{matchesKeepGoingKeyword as p,matchesNegativeKeyword as a}from"../userPromptKeywords.js";export function processTextPrompt(m,g,d,c,f,u,y){const l=t();e(l);const v="string"==typeof m?m:m.find(t=>"text"===t.type)?.text||"";n(v);const x="string"==typeof m?m:m.findLast(t=>"text"===t.type)?.text||"";x&&r("user_prompt",{prompt_length:String(x.length),prompt:i(x),"prompt.id":l});const h=a(v),_=p(v);if(s("tengu_input_prompt",{is_negative:h,is_keep_going:_}),g.length>0){const t="string"==typeof m?m.trim()?[{type:"text",text:m}]:[]:m;return{messages:[o({content:[...t,...g],uuid:f,imagePasteIds:d.length>0?d:void 0,permissionMode:u,isMeta:y||void 0}),...c],shouldQuery:!0}}return{messages:[o({content:m,uuid:f,permissionMode:u,isMeta:y||void 0}),...c],shouldQuery:!0}}
1
+ import{randomUUID as t}from"crypto";import{setPromptId as e}from"../../bootstrap/state.js";import{logEvent as s}from"../../services/analytics/index.js";import{createUserMessage as o}from"../messages.js";import{logOTelEvent as r,redactIfDisabled as i}from"../telemetry/events.js";import{startInteractionSpan as n}from"../telemetry/sessionTracing.js";import{matchesKeepGoingKeyword as p,matchesNegativeKeyword as m}from"../userPromptKeywords.js";export function processTextPrompt(g,d,u,a,f,c,y){const l=t();e(l);const x="string"==typeof g?g:g.find(t=>"text"===t.type)?.text||"";n(x);const _="string"==typeof g?g:g.findLast(t=>"text"===t.type)?.text||"";_&&r("user_prompt",{prompt_length:String(_.length),prompt:i(_),"prompt.id":l});const h=m(x),j=p(x);if(s("tengu_input_prompt",{is_negative:h,is_keep_going:j}),d.length>0){const t="string"==typeof g?g.trim()?[{type:"text",text:g}]:[]:g;return{messages:[o({content:[...t,...d],uuid:f,imagePasteIds:u.length>0?u:void 0,permissionMode:c,isMeta:y||void 0}),...a],shouldQuery:!0}}return{messages:[o({content:g,uuid:f,permissionMode:c,isMeta:y||void 0}),...a],shouldQuery:!0}}
@@ -1 +1 @@
1
- import{feature as e}from"bun:bundle";import{randomUUID as t}from"crypto";import{logEvent as s}from"src/services/analytics/index.js";import{getContentText as a}from"src/utils/messages.js";import{findCommand as o,getCommandName as n,isBridgeSafeCommand as r}from"../../commands.js";import{isValidImagePaste as i}from"../../types/textInputTypes.js";import{createAttachmentMessage as m,getAttachmentMessages as p}from"../attachments.js";import{toArray as c}from"../generators.js";import{executeUserPromptSubmitHooks as u,getUserPromptSubmitHookBlockingMessage as l}from"../hooks.js";import{createImageMetadataText as d,maybeResizeAndDownsampleImageBlock as g}from"../imageResizer.js";import{storeImages as h}from"../imageStore.js";import{createCommandInputMessage as f,createSystemMessage as y,createUserMessage as _}from"../messages.js";import{queryCheckpoint as b}from"../queryProfiler.js";import{parseSlashCommand as k}from"../slashCommandParsing.js";import{hasUltraplanKeyword as w,replaceUltraplanKeyword as x}from"../ultraplan/keyword.js";import{processTextPrompt as C}from"./processTextPrompt.js";export async function processUserInput({input:M,preExpansionInput:S,mode:P,setToolJSX:j,context:I,pastedContents:T,ideSelection:q,messages:U,setUserInputOnProcessing:$,uuid:A,isAlreadyProcessing:v,querySource:z,canUseTool:E,skipSlashCommands:O,bridgeOrigin:R,isMeta:B,skipAttachments:D}){const N="string"==typeof M?M:null;"prompt"!==P||null===N||B||$?.(N),b("query_process_user_input_base_start");const W=I.getAppState(),Q=await async function(t,a,m,u,l,y,M,S,P,j,I,T,q,U,$,A,v){let z=null,E=[];const O=[];let R=t;if("string"==typeof t)z=t;else if(t.length>0){b("query_image_processing_start");const e=[];for(const s of t)if("image"===s.type){const t=await g(s);if(t.dimensions){const e=d(t.dimensions);e&&O.push(e)}e.push(t.block)}else e.push(s);R=e,b("query_image_processing_end");const s=e[e.length-1];"text"===s?.type?(z=s.text,E=e.slice(0,-1)):E=e}if(null===z&&"prompt"!==a)throw new Error(`Mode: ${a} requires a string input.`);const B=l?Object.values(l).filter(i):[],D=B.map(e=>e.id),N=l?await h(l):new Map;b("query_pasted_image_processing_start");const W=await Promise.all(B.map(async e=>{const t={type:"image",source:{type:"base64",media_type:e.mediaType||"image/png",data:e.content}};return s("tengu_pasted_image_resize_attempt",{original_size_bytes:e.content.length}),{resized:await g(t),originalDimensions:e.dimensions,sourcePath:e.sourcePath??N.get(e.id)}})),Q=[];for(const{resized:e,originalDimensions:t,sourcePath:s}of W){if(e.dimensions){const t=d(e.dimensions,s);t&&O.push(t)}else if(t){const e=d(t,s);e&&O.push(e)}else s&&O.push(`[Image source: ${s}]`);Q.push(e.block)}b("query_pasted_image_processing_end");let L=q;if(U&&null!==z&&z.startsWith("/")){const e=k(z),t=e?o(e.commandName,u.options.commands):void 0;if(t){if(!r(t)){const e=`/${n(t)} isn't available over Remote Control.`;return{messages:[_({content:z,uuid:S}),f(`<local-command-stdout>${e}</local-command-stdout>`)],shouldQuery:!1,resultText:e}}L=!1}}if(e("ULTRAPLAN")&&"prompt"===a&&!u.options.isNonInteractiveSession&&null!==z&&!L&&!z.startsWith("/")&&!u.getAppState().ultraplanSessionUrl&&!u.getAppState().ultraplanLaunching&&w(v??z)){s("tengu_ultraplan_keyword",{});const e=x(z).trim(),{processSlashCommand:t}=await import("./processSlashCommand.js");return addImageMetadataMessage(await t(`/ultraplan ${e}`,E,Q,[],u,m,S,P,I),O)}const H=!A&&null!==z&&("prompt"!==a||L||!z.startsWith("/"));b("query_attachment_loading_start");const K=H?await c(p(z,u,y??null,[],M,j)):[];if(b("query_attachment_loading_end"),null!==z&&"bash"===a){const{processBashCommand:e}=await import("./processBashCommand.js");return addImageMetadataMessage(await e(z,E,K,u,m),O)}if(null!==z&&!L&&z.startsWith("/")){const{processSlashCommand:e}=await import("./processSlashCommand.js");return addImageMetadataMessage(await e(z,E,Q,K,u,m,S,P,I),O)}if(null!==z&&"prompt"===a){const e=z.trim(),t=K.find(e=>"agent_mention"===e.attachment.type);if(t){const a=`@agent-${t.attachment.agentType}`,o=e===a,n=e.startsWith(a)&&!o;s("tengu_subagent_at_mention",{is_subagent_only:o,is_prefix:n})}}return addImageMetadataMessage(C(R,Q,D,K,S,T,$),O)}(M,P,j,I,T,q,U,A,v,z,E,W.toolPermissionContext.mode,O,R,B,D,S);if(b("query_process_user_input_base_end"),!Q.shouldQuery)return Q;b("query_hooks_start");const L=a(M)||"";for await(const e of u(L,W.toolPermissionContext.mode,I,I.requestPrompt))if("progress"!==e.message?.type){if(e.blockingError){const t=l(e.blockingError);return{messages:[y(`${t}\n\nOriginal prompt: ${M}`,"warning")],shouldQuery:!1,allowedTools:Q.allowedTools}}if(e.preventContinuation){const t=e.stopReason?`Operation stopped by hook: ${e.stopReason}`:"Operation stopped by hook";return Q.messages.push(_({content:t})),Q.shouldQuery=!1,Q}if(e.additionalContexts&&e.additionalContexts.length>0&&Q.messages.push(m({type:"hook_additional_context",content:e.additionalContexts.map(applyTruncation),hookName:"UserPromptSubmit",toolUseID:`hook-${t()}`,hookEvent:"UserPromptSubmit"})),e.message)switch(e.message.attachment.type){case"hook_success":if(!e.message.attachment.content)break;Q.messages.push({...e.message,attachment:{...e.message.attachment,content:applyTruncation(e.message.attachment.content)}});break;default:Q.messages.push(e.message)}}return b("query_hooks_end"),Q}const M=1e4;function applyTruncation(e){return e.length>M?`${e.substring(0,M)}… [output truncated - exceeded ${M} characters]`:e}function addImageMetadataMessage(e,t){return t.length>0&&e.messages.push(_({content:t.map(e=>({type:"text",text:e})),isMeta:!0})),e}
1
+ import{feature as t}from"../../recovery/bunBundleShim.js";import{randomUUID as e}from"crypto";import{logEvent as s}from"../../services/analytics/index.js";import{getContentText as o}from"../messages.js";import{findCommand as a,getCommandName as n,isBridgeSafeCommand as r}from"../../commands.js";import{isValidImagePaste as i}from"../../types/textInputTypes.js";import{createAttachmentMessage as m,getAttachmentMessages as p}from"../attachments.js";import{toArray as c}from"../generators.js";import{executeUserPromptSubmitHooks as u,getUserPromptSubmitHookBlockingMessage as l}from"../hooks.js";import{createImageMetadataText as d,maybeResizeAndDownsampleImageBlock as g}from"../imageResizer.js";import{storeImages as h}from"../imageStore.js";import{createCommandInputMessage as f,createSystemMessage as _,createUserMessage as y}from"../messages.js";import{queryCheckpoint as b}from"../queryProfiler.js";import{parseSlashCommand as w}from"../slashCommandParsing.js";import{hasUltraplanKeyword as k,replaceUltraplanKeyword as j}from"../ultraplan/keyword.js";import{processTextPrompt as x}from"./processTextPrompt.js";export async function processUserInput({input:S,preExpansionInput:C,mode:P,setToolJSX:q,context:M,pastedContents:T,ideSelection:I,messages:$,setUserInputOnProcessing:v,uuid:U,isAlreadyProcessing:A,querySource:O,canUseTool:z,skipSlashCommands:E,bridgeOrigin:R,isMeta:W,skipAttachments:N}){const Q="string"==typeof S?S:null;"prompt"!==P||null===Q||W||v?.(Q),b("query_process_user_input_base_start");const B=M.getAppState(),D=await async function(e,o,m,u,l,_,S,C,P,q,M,T,I,$,v,U,A){let O=null,z=[];const E=[];let R=e;if("string"==typeof e)O=e;else if(e.length>0){b("query_image_processing_start");const t=[];for(const s of e)if("image"===s.type){const e=await g(s);if(e.dimensions){const t=d(e.dimensions);t&&E.push(t)}t.push(e.block)}else t.push(s);R=t,b("query_image_processing_end");const s=t[t.length-1];"text"===s?.type?(O=s.text,z=t.slice(0,-1)):z=t}if(null===O&&"prompt"!==o)throw new Error(`Mode: ${o} requires a string input.`);const W=l?Object.values(l).filter(i):[],N=W.map(t=>t.id),Q=l?await h(l):new Map;b("query_pasted_image_processing_start");const B=await Promise.all(W.map(async t=>{const e={type:"image",source:{type:"base64",media_type:t.mediaType||"image/png",data:t.content}};s("tengu_pasted_image_resize_attempt",{original_size_bytes:t.content.length});return{resized:await g(e),originalDimensions:t.dimensions,sourcePath:t.sourcePath??Q.get(t.id)}})),D=[];for(const{resized:t,originalDimensions:e,sourcePath:s}of B){if(t.dimensions){const e=d(t.dimensions,s);e&&E.push(e)}else if(e){const t=d(e,s);t&&E.push(t)}else s&&E.push(`[Image source: ${s}]`);D.push(t.block)}b("query_pasted_image_processing_end");let L=I;if($&&null!==O&&O.startsWith("/")){const t=w(O),e=t?a(t.commandName,u.options.commands):void 0;if(e){if(!r(e)){const t=`/${n(e)} isn't available over Remote Control.`;return{messages:[y({content:O,uuid:C}),f(`<local-command-stdout>${t}</local-command-stdout>`)],shouldQuery:!1,resultText:t}}L=!1}}if(t("ULTRAPLAN")&&"prompt"===o&&!u.options.isNonInteractiveSession&&null!==O&&!L&&!O.startsWith("/")&&!u.getAppState().ultraplanSessionUrl&&!u.getAppState().ultraplanLaunching&&k(A??O)){s("tengu_ultraplan_keyword",{});const t=j(O).trim(),{processSlashCommand:e}=await import("./processSlashCommand.js");return addImageMetadataMessage(await e(`/ultraplan ${t}`,z,D,[],u,m,C,P,M),E)}const J=!U&&null!==O&&("prompt"!==o||L||!O.startsWith("/"));b("query_attachment_loading_start");const X=J?await c(p(O,u,_??null,[],S,q)):[];if(b("query_attachment_loading_end"),null!==O&&"bash"===o){const{processBashCommand:t}=await import("./processBashCommand.js");return addImageMetadataMessage(await t(O,z,X,u,m),E)}if(null!==O&&!L&&O.startsWith("/")){const{processSlashCommand:t}=await import("./processSlashCommand.js");return addImageMetadataMessage(await t(O,z,D,X,u,m,C,P,M),E)}if(null!==O&&"prompt"===o){const t=O.trim(),e=X.find(t=>"agent_mention"===t.attachment.type);if(e){const o=`@agent-${e.attachment.agentType}`,a=t===o,n=t.startsWith(o)&&!a;s("tengu_subagent_at_mention",{is_subagent_only:a,is_prefix:n})}}return addImageMetadataMessage(x(R,D,N,X,C,T,v),E)}(S,P,q,M,T,I,$,U,A,O,z,B.toolPermissionContext.mode,E,R,W,N,C);if(b("query_process_user_input_base_end"),!D.shouldQuery)return D;b("query_hooks_start");const L=o(S)||"";for await(const t of u(L,B.toolPermissionContext.mode,M,M.requestPrompt))if("progress"!==t.message?.type){if(t.blockingError){const e=l(t.blockingError);return{messages:[_(`${e}\n\nOriginal prompt: ${S}`,"warning")],shouldQuery:!1,allowedTools:D.allowedTools}}if(t.preventContinuation){const e=t.stopReason?`Operation stopped by hook: ${t.stopReason}`:"Operation stopped by hook";return D.messages.push(y({content:e})),D.shouldQuery=!1,D}if(t.additionalContexts&&t.additionalContexts.length>0&&D.messages.push(m({type:"hook_additional_context",content:t.additionalContexts.map(applyTruncation),hookName:"UserPromptSubmit",toolUseID:`hook-${e()}`,hookEvent:"UserPromptSubmit"})),t.message)switch(t.message.attachment.type){case"hook_success":if(!t.message.attachment.content)break;D.messages.push({...t.message,attachment:{...t.message.attachment,content:applyTruncation(t.message.attachment.content)}});break;default:D.messages.push(t.message)}}return b("query_hooks_end"),D}const S=1e4;function applyTruncation(t){return t.length>S?`${t.substring(0,S)}… [output truncated - exceeded ${S} characters]`:t}function addImageMetadataMessage(t,e){return e.length>0&&t.messages.push(y({content:e.map(t=>({type:"text",text:t})),isMeta:!0})),t}
@@ -1 +1 @@
1
- import{createRequire as r}from"module";const t=r(import.meta.url);import{formatFileSize as e}from"./format.js";let o=null;export function getPerformance(){return o||(o=t("perf_hooks").performance),o}export function formatMs(r){return r.toFixed(3)}export function formatTimelineLine(r,t,o,a,m,n,f=""){const s=a?` | RSS: ${e(a.rss)}, Heap: ${e(a.heapUsed)}`:"";return`[+${formatMs(r).padStart(m)}ms] (+${formatMs(t).padStart(n)}ms) ${o}${f}${s}`}
1
+ import{createRequire as r}from"module";const t=r(import.meta.url);import{formatFileSize as o}from"./format.js";let e=null;export function getPerformance(){return e||(e=t("perf_hooks").performance),e}export function formatMs(r){return r.toFixed(3)}export function formatTimelineLine(r,t,e,m,n,a,f=""){const p=m?` | RSS: ${o(m.rss)}, Heap: ${o(m.heapUsed)}`:"";return`[+${formatMs(r).padStart(n)}ms] (+${formatMs(t).padStart(a)}ms) ${e}${f}${p}`}
@@ -1 +1 @@
1
- import{DEFAULT_OUTPUT_STYLE_NAME as t,OUTPUT_STYLE_CONFIG as e}from"../constants/outputStyles.js";import{getSettings_DEPRECATED as r}from"./settings/settings.js";export function getQuerySourceForAgent(t,e){return e?t?`agent:builtin:${t}`:"agent:default":"agent:custom"}export function getQuerySourceForREPL(){const n=r(),o=n?.outputStyle??t;return o===t?"repl_main_thread":o in e?`repl_main_thread:outputStyle:${o}`:"repl_main_thread:outputStyle:custom"}
1
+ import{DEFAULT_OUTPUT_STYLE_NAME as t,OUTPUT_STYLE_CONFIG as e}from"../constants/outputStyles.js";import{getSettings_DEPRECATED as r}from"./settings/settings.js";export function getQuerySourceForAgent(t,e){return e?t?`agent:builtin:${t}`:"agent:default":"agent:custom"}export function getQuerySourceForREPL(){const n=r(),u=n?.outputStyle??t;if(u===t)return"repl_main_thread";return u in e?`repl_main_thread:outputStyle:${u}`:"repl_main_thread:outputStyle:custom"}
@@ -1 +1 @@
1
- import{expandPastedTextRefs as t,formatPastedTextRef as e,getPastedTextRefNumLines as n}from"../history.js";import r from"../ink/instances.js";import{classifyGuiEditor as o,getExternalEditor as s}from"./editor.js";import{execSync_DEPRECATED as i}from"./execSyncWrapper.js";import{getFsImplementation as c}from"./fsOperations.js";import{toIDEDisplayName as a}from"./ide.js";import{writeFileSync_DEPRECATED as l}from"./slowOperations.js";import{generateTempFilePath as u}from"./tempfile.js";const f={code:"code -w",subl:"subl --wait"};export function editFileInEditor(t){const e=c(),n=r.get(process.stdout);if(!n)throw new Error("Ink instance not found - cannot pause rendering");const l=s();if(!l)return{content:null};try{e.statSync(t)}catch{return{content:null}}const u=!function(t){return void 0!==o(t)}(l);u?n.enterAlternateScreen():(n.pause(),n.suspendStdin());try{return i(`${f[l]??l} "${t}"`,{stdio:"inherit"}),{content:e.readFileSync(t,{encoding:"utf-8"})}}catch(t){if("object"==typeof t&&null!==t&&"status"in t&&"number"==typeof t.status){const e=t.status;if(0!==e)return{content:null,error:`${a(l)} exited with code ${e}`}}return{content:null}}finally{u?n.exitAlternateScreen():(n.resumeStdin(),n.resume())}}export function editPromptInEditor(r,o){const s=c(),i=u();try{const s=o?t(r,o):r;l(i,s,{encoding:"utf-8",flush:!0});const c=editFileInEditor(i);if(null===c.content)return c;let a=c.content;return a.endsWith("\n")&&!a.endsWith("\n\n")&&(a=a.slice(0,-1)),o&&(a=function(t,r,o){let s=t;for(const[t,r]of Object.entries(o))if("text"===r.type){const o=parseInt(t),i=r.content,c=s.indexOf(i);if(-1!==c){const t=n(i),r=e(o,t);s=s.slice(0,c)+r+s.slice(c+i.length)}}return s}(a,0,o)),{content:a}}finally{try{s.unlinkSync(i)}catch{}}}
1
+ import{expandPastedTextRefs as t,formatPastedTextRef as n,getPastedTextRefNumLines as e}from"../history.js";import r from"../ink/instances.js";import{classifyGuiEditor as o,getExternalEditor as i}from"./editor.js";import{execSync_DEPRECATED as s}from"./execSyncWrapper.js";import{getFsImplementation as c}from"./fsOperations.js";import{toIDEDisplayName as u}from"./ide.js";import{writeFileSync_DEPRECATED as l}from"./slowOperations.js";import{generateTempFilePath as f}from"./tempfile.js";const d={code:"code -w",subl:"subl --wait"};export function editFileInEditor(t){const n=c(),e=r.get(process.stdout);if(!e)throw new Error("Ink instance not found - cannot pause rendering");const l=i();if(!l)return{content:null};try{n.statSync(t)}catch{return{content:null}}const f=!function(t){return void 0!==o(t)}(l);f?e.enterAlternateScreen():(e.pause(),e.suspendStdin());try{s(`${d[l]??l} "${t}"`,{stdio:"inherit"});return{content:n.readFileSync(t,{encoding:"utf-8"})}}catch(t){if("object"==typeof t&&null!==t&&"status"in t&&"number"==typeof t.status){const n=t.status;if(0!==n){return{content:null,error:`${u(l)} exited with code ${n}`}}}return{content:null}}finally{f?e.exitAlternateScreen():(e.resumeStdin(),e.resume())}}export function editPromptInEditor(r,o){const i=c(),s=f();try{const i=o?t(r,o):r;l(s,i,{encoding:"utf-8",flush:!0});const c=editFileInEditor(s);if(null===c.content)return c;let u=c.content;return u.endsWith("\n")&&!u.endsWith("\n\n")&&(u=u.slice(0,-1)),o&&(u=function(t,r,o){let i=t;for(const[t,r]of Object.entries(o))if("text"===r.type){const o=parseInt(t),s=r.content,c=i.indexOf(s);if(-1!==c){const t=e(s),r=n(o,t);i=i.slice(0,c)+r+i.slice(c+s.length)}}return i}(u,0,o)),{content:u}}finally{try{i.unlinkSync(s)}catch{}}}
@@ -1 +1 @@
1
- import{createRequire as o}from"module";const r=o(import.meta.url);import{randomUUID as t}from"crypto";import{BashTool as e}from"../tools/BashTool/BashTool.js";import{logForDebugging as s}from"./debug.js";import{errorMessage as a,MalformedCommandError as n,ShellError as m}from"./errors.js";import{createAssistantMessage as l}from"./messages.js";import{hasPermissionsToUseTool as i}from"./permissions/permissions.js";import{processToolResultBlock as c}from"./toolResultStorage.js";import{isPowerShellToolEnabled as h}from"./shell/shellToolUtils.js";const p=(()=>{let o;return()=>(o||(o=r("../tools/PowerShellTool/PowerShellTool.js").PowerShellTool),o)})(),d=/```!\s*\n?([\s\S]*?)\n?```/g,f=/(?<=^|\s)!`([^`]+)`/gm;export async function executeShellCommandsInPrompt(o,r,u,w){let g=o;const S="powershell"===w&&h()?p():e,$=o.matchAll(d),T=o.includes("!`")?o.matchAll(f):[];return await Promise.all([...$,...T].map(async o=>{const e=o[1]?.trim();if(e)try{const a=await i(S,{command:e},r,l({content:[]}),"");if("allow"!==a.behavior)throw s(`Shell command permission check failed for command in ${u}: ${e}. Error: ${a.message}`),new n(`Shell command permission check failed for pattern "${o[0]}": ${a.message||"Permission denied"}`);const{data:m}=await S.call({command:e},r),h=await c(S,m,t()),p="string"==typeof h.content?h.content:formatBashOutput(m.stdout,m.stderr);g=g.replace(o[0],()=>p)}catch(r){if(r instanceof n)throw r;!function(o,r,t=!1){if(o instanceof m){if(o.interrupted)throw new n(`Shell command interrupted for pattern "${r}": [Command interrupted]`);const e=formatBashOutput(o.stdout,o.stderr,t);throw new n(`Shell command failed for pattern "${r}": ${e}`)}const e=a(o);throw new n(t?`[Error: ${e}]`:`[Error]\n${e}`)}(r,o[0])}})),g}function formatBashOutput(o,r,t=!1){const e=[];return o.trim()&&e.push(o.trim()),r.trim()&&(t?e.push(`[stderr: ${r.trim()}]`):e.push(`[stderr]\n${r.trim()}`)),e.join(t?" ":"\n")}
1
+ import{createRequire as o}from"module";const t=o(import.meta.url);import{randomUUID as r}from"crypto";import{BashTool as e}from"../tools/BashTool/BashTool.js";import{logForDebugging as s}from"./debug.js";import{errorMessage as n,MalformedCommandError as m,ShellError as i}from"./errors.js";import{createAssistantMessage as l}from"./messages.js";import{hasPermissionsToUseTool as a}from"./permissions/permissions.js";import{processToolResultBlock as c}from"./toolResultStorage.js";import{isPowerShellToolEnabled as p}from"./shell/shellToolUtils.js";const f=(()=>{let o;return()=>(o||(o=t("../tools/PowerShellTool/PowerShellTool.js").PowerShellTool),o)})(),h=/```!\s*\n?([\s\S]*?)\n?```/g,d=/(?<=^|\s)!`([^`]+)`/gm;export async function executeShellCommandsInPrompt(o,t,u,w){let $=o;const S="powershell"===w&&p()?f():e,j=o.matchAll(h),g=o.includes("!`")?o.matchAll(d):[];return await Promise.all([...j,...g].map(async o=>{const e=o[1]?.trim();if(e)try{const n=await a(S,{command:e},t,l({content:[]}),"");if("allow"!==n.behavior)throw s(`Shell command permission check failed for command in ${u}: ${e}. Error: ${n.message}`),new m(`Shell command permission check failed for pattern "${o[0]}": ${n.message||"Permission denied"}`);const{data:i}=await S.call({command:e},t),p=await c(S,i,r()),f="string"==typeof p.content?p.content:formatBashOutput(i.stdout,i.stderr);$=$.replace(o[0],()=>f)}catch(t){if(t instanceof m)throw t;!function(o,t,r=!1){if(o instanceof i){if(o.interrupted)throw new m(`Shell command interrupted for pattern "${t}": [Command interrupted]`);const e=formatBashOutput(o.stdout,o.stderr,r);throw new m(`Shell command failed for pattern "${t}": ${e}`)}const e=n(o);throw new m(r?`[Error: ${e}]`:`[Error]\n${e}`)}(t,o[0])}})),$}function formatBashOutput(o,t,r=!1){const e=[];return o.trim()&&e.push(o.trim()),t.trim()&&(r?e.push(`[stderr: ${t.trim()}]`):e.push(`[stderr]\n${t.trim()}`)),e.join(r?" ":"\n")}
@@ -1 +1 @@
1
- import{createRequire as t}from"module";const e=t(import.meta.url);import r from"axios";import{HttpsProxyAgent as o}from"https-proxy-agent";import s from"lodash-es/memoize.js";import{getCACertificates as n}from"./caCerts.js";import{logForDebugging as p}from"./debug.js";import{isEnvTruthy as i}from"./envUtils.js";import{getMTLSAgent as c,getMTLSConfig as a,getTLSFetchOptions as u}from"./mtls.js";let l,g=!1;export function disableKeepAlive(){g=!0}export function _resetKeepAliveForTesting(){g=!1}export function getAddressFamily(t){switch(t.family){case 0:case 4:case 6:return t.family;case"IPv6":return 6;case"IPv4":case void 0:return 4;default:throw new Error(`Unsupported address family: ${t.family}`)}}export function getProxyUrl(t=process.env){return t.https_proxy||t.HTTPS_PROXY||t.http_proxy||t.HTTP_PROXY}export function getNoProxy(t=process.env){return t.no_proxy||t.NO_PROXY}export function shouldBypassProxy(t,e=getNoProxy()){if(!e)return!1;if("*"===e)return!0;try{const r=new URL(t),o=r.hostname.toLowerCase(),s=r.port||("https:"===r.protocol?"443":"80"),n=`${o}:${s}`;return e.split(/[,\s]+/).filter(Boolean).some(t=>{if((t=t.toLowerCase().trim()).includes(":"))return n===t;if(t.startsWith(".")){const e=t;return o===t.substring(1)||o.endsWith(e)}return o===t})}catch{return!1}}function createHttpsProxyAgent(t,e={}){const r=a(),s=n(),p={...r&&{cert:r.cert,key:r.key,passphrase:r.passphrase},...s&&{ca:s}};return(i(process.env.CONTEXT_CODE_PROXY_RESOLVES_HOSTS)||i(process.env.CLAUDE_CODE_PROXY_RESOLVES_HOSTS))&&(p.lookup=(t,e,r)=>{r(null,t,getAddressFamily(e))}),new o(t,{...p,...e})}export function createAxiosInstance(t={}){const e=getProxyUrl(),o=c(),s=r.create({proxy:!1});if(!e)return o&&(s.defaults.httpsAgent=o),s;const n=createHttpsProxyAgent(e,t);return s.interceptors.request.use(t=>(t.url&&shouldBypassProxy(t.url)?(t.httpsAgent=o,t.httpAgent=o):(t.httpsAgent=n,t.httpAgent=n),t)),s}export const getProxyAgent=s(t=>{const r=e("undici"),o=a(),s=n(),p={httpProxy:t,httpsProxy:t,noProxy:process.env.NO_PROXY||process.env.no_proxy};if(o||s){const t={...o&&{cert:o.cert,key:o.key,passphrase:o.passphrase},...s&&{ca:s}};p.connect=t,p.requestTls=t}return new r.EnvHttpProxyAgent(p)});export function getWebSocketProxyAgent(t){const e=getProxyUrl();if(e&&!shouldBypassProxy(t))return createHttpsProxyAgent(e)}export function getWebSocketProxyUrl(t){const e=getProxyUrl();if(e&&!shouldBypassProxy(t))return e}export function getProxyFetchOptions(t){const e=g?{keepalive:!1}:{};if(t?.forAnthropicAPI){const t=process.env.ANTHROPIC_UNIX_SOCKET;if(t&&"undefined"!=typeof Bun)return{...e,unix:t}}const r=getProxyUrl();return r?"undefined"!=typeof Bun?{...e,proxy:r,...u()}:{...e,dispatcher:getProxyAgent(r)}:{...e,...u()}}export function configureGlobalAgents(){const t=getProxyUrl(),o=c();if(void 0!==l&&(r.interceptors.request.eject(l),l=void 0),r.defaults.proxy=void 0,r.defaults.httpAgent=void 0,r.defaults.httpsAgent=void 0,t){r.defaults.proxy=!1;const s=createHttpsProxyAgent(t);l=r.interceptors.request.use(t=>(t.url&&shouldBypassProxy(t.url)?o?(t.httpsAgent=o,t.httpAgent=o):(delete t.httpsAgent,delete t.httpAgent):(t.httpsAgent=s,t.httpAgent=s),t)),e("undici").setGlobalDispatcher(getProxyAgent(t))}else if(o){r.defaults.httpsAgent=o;const t=u();t.dispatcher&&e("undici").setGlobalDispatcher(t.dispatcher)}}export async function getAWSClientProxyConfig(){const t=getProxyUrl();if(!t)return{};const[{NodeHttpHandler:e},{defaultProvider:r}]=await Promise.all([import("@smithy/node-http-handler"),import("@aws-sdk/credential-provider-node")]),o=createHttpsProxyAgent(t),s=new e({httpAgent:o,httpsAgent:o});return{requestHandler:s,credentials:r({clientConfig:{requestHandler:s}})}}export function clearProxyCache(){getProxyAgent.cache.clear?.(),p("Cleared proxy agent cache")}
1
+ import{createRequire as t}from"module";const e=t(import.meta.url);import r from"axios";import{HttpsProxyAgent as o}from"https-proxy-agent";import n from"lodash-es/memoize.js";import{getCACertificates as s}from"./caCerts.js";import{logForDebugging as p}from"./debug.js";import{isEnvTruthy as i}from"./envUtils.js";import{getMTLSAgent as c,getMTLSConfig as a,getTLSFetchOptions as u}from"./mtls.js";let l,y=!1;export function disableKeepAlive(){y=!0}export function _resetKeepAliveForTesting(){y=!1}export function getAddressFamily(t){switch(t.family){case 0:case 4:case 6:return t.family;case"IPv6":return 6;case"IPv4":case void 0:return 4;default:throw new Error(`Unsupported address family: ${t.family}`)}}export function getProxyUrl(t=process.env){return t.https_proxy||t.HTTPS_PROXY||t.http_proxy||t.HTTP_PROXY}export function getNoProxy(t=process.env){return t.no_proxy||t.NO_PROXY}export function shouldBypassProxy(t,e=getNoProxy()){if(!e)return!1;if("*"===e)return!0;try{const r=new URL(t),o=r.hostname.toLowerCase(),n=r.port||("https:"===r.protocol?"443":"80"),s=`${o}:${n}`;return e.split(/[,\s]+/).filter(Boolean).some(t=>{if((t=t.toLowerCase().trim()).includes(":"))return s===t;if(t.startsWith(".")){const e=t;return o===t.substring(1)||o.endsWith(e)}return o===t})}catch{return!1}}function createHttpsProxyAgent(t,e={}){const r=a(),n=s(),p={...r&&{cert:r.cert,key:r.key,passphrase:r.passphrase},...n&&{ca:n}};return(i(process.env.CONTEXT_CODE_PROXY_RESOLVES_HOSTS)||i(process.env.CLAUDE_CODE_PROXY_RESOLVES_HOSTS))&&(p.lookup=(t,e,r)=>{r(null,t,getAddressFamily(e))}),new o(t,{...p,...e})}export function createAxiosInstance(t={}){const e=getProxyUrl(),o=c(),n=r.create({proxy:!1});if(!e)return o&&(n.defaults.httpsAgent=o),n;const s=createHttpsProxyAgent(e,t);return n.interceptors.request.use(t=>(t.url&&shouldBypassProxy(t.url)?(t.httpsAgent=o,t.httpAgent=o):(t.httpsAgent=s,t.httpAgent=s),t)),n}export const getProxyAgent=n(t=>{const r=e("undici"),o=a(),n=s(),p={httpProxy:t,httpsProxy:t,noProxy:process.env.NO_PROXY||process.env.no_proxy};if(o||n){const t={...o&&{cert:o.cert,key:o.key,passphrase:o.passphrase},...n&&{ca:n}};p.connect=t,p.requestTls=t}return new r.EnvHttpProxyAgent(p)});export function getWebSocketProxyAgent(t){const e=getProxyUrl();if(e&&!shouldBypassProxy(t))return createHttpsProxyAgent(e)}export function getWebSocketProxyUrl(t){const e=getProxyUrl();if(e&&!shouldBypassProxy(t))return e}export function getProxyFetchOptions(t){const e=y?{keepalive:!1}:{};if(t?.forAnthropicAPI){const t=process.env.ANTHROPIC_UNIX_SOCKET;if(t&&"undefined"!=typeof Bun)return{...e,unix:t}}const r=getProxyUrl();return r?"undefined"!=typeof Bun?{...e,proxy:r,...u()}:{...e,dispatcher:getProxyAgent(r)}:{...e,...u()}}export function configureGlobalAgents(){const t=getProxyUrl(),o=c();if(void 0!==l&&(r.interceptors.request.eject(l),l=void 0),r.defaults.proxy=void 0,r.defaults.httpAgent=void 0,r.defaults.httpsAgent=void 0,t){r.defaults.proxy=!1;const n=createHttpsProxyAgent(t);l=r.interceptors.request.use(t=>(t.url&&shouldBypassProxy(t.url)?o?(t.httpsAgent=o,t.httpAgent=o):(delete t.httpsAgent,delete t.httpAgent):(t.httpsAgent=n,t.httpAgent=n),t)),e("undici").setGlobalDispatcher(getProxyAgent(t))}else if(o){r.defaults.httpsAgent=o;const t=u();t.dispatcher&&e("undici").setGlobalDispatcher(t.dispatcher)}}export async function getAWSClientProxyConfig(){const t=getProxyUrl();if(!t)return{};const[{NodeHttpHandler:e},{defaultProvider:r}]=await Promise.all([import("@smithy/node-http-handler"),import("@aws-sdk/credential-provider-node")]),o=createHttpsProxyAgent(t),n=new e({httpAgent:o,httpsAgent:o});return{requestHandler:n,credentials:r({clientConfig:{requestHandler:n}})}}export function clearProxyCache(){getProxyAgent.cache.clear?.(),p("Cleared proxy agent cache")}
@@ -1 +1 @@
1
- import e from"lodash-es/last.js";import{getSessionId as t,isSessionPersistenceDisabled as s}from"src/bootstrap/state.js";import{runTools as o}from"../services/tools/toolOrchestration.js";import{findToolByName as i}from"../Tool.js";import{BASH_TOOL_NAME as n}from"../tools/BashTool/toolName.js";import{FILE_EDIT_TOOL_NAME as a}from"../tools/FileEditTool/constants.js";import{FILE_READ_TOOL_NAME as r,FILE_UNCHANGED_STUB as l}from"../tools/FileReadTool/prompt.js";import{FILE_WRITE_TOOL_NAME as p}from"../tools/FileWriteTool/prompt.js";import{logForDebugging as m}from"./debug.js";import{isEnvTruthy as c}from"./envUtils.js";import{isFsInaccessible as f}from"./errors.js";import{getFileModificationTime as u,stripLineNumberPrefix as d}from"./file.js";import{readFileSyncWithMetadata as _}from"./fileRead.js";import{createFileStateCacheWithSizeLimit as y}from"./fileStateCache.js";import{isNotEmptyMessage as g,normalizeMessages as h}from"./messages.js";import{expandPath as T}from"./path.js";import{recordTranscript as E}from"./sessionStorage.js";export function isResultSuccessful(t,s=null){if(!t)return!1;if("assistant"===t.type){const s=e(t.message.content);return"text"===s?.type||"thinking"===s?.type||"redacted_thinking"===s?.type}if("user"===t.type){const e=t.message.content;if(Array.isArray(e)&&e.length>0&&e.every(e=>"type"in e&&"tool_result"===e.type))return!0}return"end_turn"===s}const A=new Map;export function*normalizeMessage(e){switch(e.type){case"assistant":for(const s of h([e]))g(s)&&(yield{type:"assistant",message:s.message,parent_tool_use_id:null,session_id:t(),uuid:s.uuid,error:s.error});return;case"progress":if("agent_progress"===e.data.type||"skill_progress"===e.data.type)for(const s of h([e.data.message]))switch(s.type){case"assistant":if(!g(s))break;yield{type:"assistant",message:s.message,parent_tool_use_id:e.parentToolUseID,session_id:t(),uuid:s.uuid,error:s.error};break;case"user":yield{type:"user",message:s.message,parent_tool_use_id:e.parentToolUseID,session_id:t(),uuid:s.uuid,timestamp:s.timestamp,isSynthetic:s.isMeta||s.isVisibleInTranscriptOnly,tool_use_result:s.mcpMeta?{content:s.toolUseResult,...s.mcpMeta}:s.toolUseResult}}else if("bash_progress"===e.data.type||"powershell_progress"===e.data.type){if(!(c(process.env.CONTEXT_CODE_REMOTE)||c(process.env.CLAUDE_CODE_REMOTE)||process.env.CONTEXT_CODE_CONTAINER_ID||process.env.CLAUDE_CODE_CONTAINER_ID))break;const s=e.parentToolUseID,o=Date.now();if(o-(A.get(s)||0)>=3e4){if(A.size>=100){const e=A.keys().next().value;void 0!==e&&A.delete(e)}A.set(s,o),yield{type:"tool_progress",tool_use_id:e.toolUseID,tool_name:"bash_progress"===e.data.type?"Bash":"PowerShell",parent_tool_use_id:e.parentToolUseID,elapsed_time_seconds:e.data.elapsedTimeSeconds,task_id:e.data.taskId,session_id:t(),uuid:e.uuid}}}break;case"user":for(const s of h([e]))yield{type:"user",message:s.message,parent_tool_use_id:null,session_id:t(),uuid:s.uuid,timestamp:s.timestamp,isSynthetic:s.isMeta||s.isVisibleInTranscriptOnly,tool_use_result:s.mcpMeta?{content:s.toolUseResult,...s.mcpMeta}:s.toolUseResult};return}}export async function*handleOrphanedPermission(e,n,a,r){const l=!s(),{permissionResult:p,assistantMessage:c}=e,{toolUseID:f}=p;if(!f)return;const u=c.message.content;let d;if(Array.isArray(u))for(const e of u)if("tool_use"===e.type&&e.id===f){d=e;break}if(!d)return;const _=d.name,y=d.input;if(!i(n,_))return;let g=y;"allow"===p.behavior&&(void 0!==p.updatedInput?g=p.updatedInput:m(`Orphaned permission for ${_}: updatedInput is undefined, falling back to original tool input`,{level:"warn"}));const h={...d,input:g},canUseTool=async()=>({...p,decisionReason:{type:"mode",mode:"default"}});a.some(e=>"assistant"===e.type&&Array.isArray(e.message.content)&&e.message.content.some(e=>"tool_use"===e.type&&"id"in e&&e.id===f))||(a.push(c),l&&await E(a));const T={...c,session_id:t(),parent_tool_use_id:null};yield T;for await(const e of o([h],[c],canUseTool,r))if(e.message){a.push(e.message),l&&await E(a);const s={...e.message,session_id:t(),parent_tool_use_id:null};yield s}}export function extractReadFilesFromMessages(e,t,s=10){const o=y(s),i=new Map,n=new Map,m=new Map;for(const s of e)if("assistant"===s.type&&Array.isArray(s.message.content))for(const e of s.message.content)if("tool_use"===e.type&&e.name===r){const s=e.input;if(s?.file_path&&void 0===s?.offset&&void 0===s?.limit){const o=T(s.file_path,t);i.set(e.id,o)}}else if("tool_use"===e.type&&e.name===p){const s=e.input;if(s?.file_path&&s?.content){const o=T(s.file_path,t);n.set(e.id,{filePath:o,content:s.content})}}else if("tool_use"===e.type&&e.name===a){const s=e.input;if(s?.file_path){const o=T(s.file_path,t);m.set(e.id,o)}}for(const t of e)if("user"===t.type&&Array.isArray(t.message.content))for(const s of t.message.content)if("tool_result"===s.type&&s.tool_use_id){const a=i.get(s.tool_use_id);if(a&&"string"==typeof s.content&&!s.content.startsWith(l)){const e=s.content.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g,"").split("\n").map(d).join("\n").trim();if(t.timestamp){const s=new Date(t.timestamp).getTime();o.set(a,{content:e,timestamp:s,offset:void 0,limit:void 0})}}const r=n.get(s.tool_use_id);if(r&&t.timestamp){const e=new Date(t.timestamp).getTime();o.set(r.filePath,{content:r.content,timestamp:e,offset:void 0,limit:void 0})}const p=m.get(s.tool_use_id);if(p&&!0!==s.is_error)try{const{content:e}=_(p);o.set(p,{content:e,timestamp:u(p),offset:void 0,limit:void 0})}catch(e){if(!f(e))throw e}}return o}export function extractBashToolsFromMessages(e){const t=new Set;for(const s of e)if("assistant"===s.type&&Array.isArray(s.message.content))for(const e of s.message.content)if("tool_use"===e.type&&e.name===n){const{input:s}=e;if("object"!=typeof s||null===s||!("command"in s))continue;const o=extractCliName("string"==typeof s.command?s.command:void 0);o&&t.add(o)}return t}const I=new Set(["sudo"]);function extractCliName(e){if(!e)return;const t=e.trim().split(/\s+/);for(const e of t)if(!/^[A-Za-z_]\w*=/.test(e)&&!I.has(e))return e}
1
+ import e from"lodash-es/last.js";import{getSessionId as t,isSessionPersistenceDisabled as s}from"../bootstrap/state.js";import{runTools as o}from"../services/tools/toolOrchestration.js";import{findToolByName as i}from"../Tool.js";import{BASH_TOOL_NAME as n}from"../tools/BashTool/toolName.js";import{FILE_EDIT_TOOL_NAME as r}from"../tools/FileEditTool/constants.js";import{FILE_READ_TOOL_NAME as a,FILE_UNCHANGED_STUB as p}from"../tools/FileReadTool/prompt.js";import{FILE_WRITE_TOOL_NAME as l}from"../tools/FileWriteTool/prompt.js";import{logForDebugging as m}from"./debug.js";import{isEnvTruthy as c}from"./envUtils.js";import{isFsInaccessible as f}from"./errors.js";import{getFileModificationTime as u,stripLineNumberPrefix as d}from"./file.js";import{readFileSyncWithMetadata as _}from"./fileRead.js";import{createFileStateCacheWithSizeLimit as y}from"./fileStateCache.js";import{isNotEmptyMessage as g,normalizeMessages as h}from"./messages.js";import{expandPath as T}from"./path.js";import{recordTranscript as v}from"./sessionStorage.js";export function isResultSuccessful(t,s=null){if(!t)return!1;if("assistant"===t.type){const s=e(t.message.content);return"text"===s?.type||"thinking"===s?.type||"redacted_thinking"===s?.type}if("user"===t.type){const e=t.message.content;if(Array.isArray(e)&&e.length>0&&e.every(e=>"type"in e&&"tool_result"===e.type))return!0}return"end_turn"===s}const w=new Map;export function*normalizeMessage(e){switch(e.type){case"assistant":for(const s of h([e]))g(s)&&(yield{type:"assistant",message:s.message,parent_tool_use_id:null,session_id:t(),uuid:s.uuid,error:s.error});return;case"progress":if("agent_progress"===e.data.type||"skill_progress"===e.data.type)for(const s of h([e.data.message]))switch(s.type){case"assistant":if(!g(s))break;yield{type:"assistant",message:s.message,parent_tool_use_id:e.parentToolUseID,session_id:t(),uuid:s.uuid,error:s.error};break;case"user":yield{type:"user",message:s.message,parent_tool_use_id:e.parentToolUseID,session_id:t(),uuid:s.uuid,timestamp:s.timestamp,isSynthetic:s.isMeta||s.isVisibleInTranscriptOnly,tool_use_result:s.mcpMeta?{content:s.toolUseResult,...s.mcpMeta}:s.toolUseResult}}else if("bash_progress"===e.data.type||"powershell_progress"===e.data.type){if(!(c(process.env.CONTEXT_CODE_REMOTE)||c(process.env.CLAUDE_CODE_REMOTE)||process.env.CONTEXT_CODE_CONTAINER_ID||process.env.CLAUDE_CODE_CONTAINER_ID))break;const s=e.parentToolUseID,o=Date.now();if(o-(w.get(s)||0)>=3e4){if(w.size>=100){const e=w.keys().next().value;void 0!==e&&w.delete(e)}w.set(s,o),yield{type:"tool_progress",tool_use_id:e.toolUseID,tool_name:"bash_progress"===e.data.type?"Bash":"PowerShell",parent_tool_use_id:e.parentToolUseID,elapsed_time_seconds:e.data.elapsedTimeSeconds,task_id:e.data.taskId,session_id:t(),uuid:e.uuid}}}break;case"user":for(const s of h([e]))yield{type:"user",message:s.message,parent_tool_use_id:null,session_id:t(),uuid:s.uuid,timestamp:s.timestamp,isSynthetic:s.isMeta||s.isVisibleInTranscriptOnly,tool_use_result:s.mcpMeta?{content:s.toolUseResult,...s.mcpMeta}:s.toolUseResult};return}}export async function*handleOrphanedPermission(e,n,r,a){const p=!s(),{permissionResult:l,assistantMessage:c}=e,{toolUseID:f}=l;if(!f)return;const u=c.message.content;let d;if(Array.isArray(u))for(const e of u)if("tool_use"===e.type&&e.id===f){d=e;break}if(!d)return;const _=d.name,y=d.input;if(!i(n,_))return;let g=y;"allow"===l.behavior&&(void 0!==l.updatedInput?g=l.updatedInput:m(`Orphaned permission for ${_}: updatedInput is undefined, falling back to original tool input`,{level:"warn"}));const h={...d,input:g},canUseTool=async()=>({...l,decisionReason:{type:"mode",mode:"default"}});r.some(e=>"assistant"===e.type&&Array.isArray(e.message.content)&&e.message.content.some(e=>"tool_use"===e.type&&"id"in e&&e.id===f))||(r.push(c),p&&await v(r));const T={...c,session_id:t(),parent_tool_use_id:null};yield T;for await(const e of o([h],[c],canUseTool,a))if(e.message){r.push(e.message),p&&await v(r);const s={...e.message,session_id:t(),parent_tool_use_id:null};yield s}}export function extractReadFilesFromMessages(e,t,s=10){const o=y(s),i=new Map,n=new Map,m=new Map;for(const s of e)if("assistant"===s.type&&Array.isArray(s.message.content))for(const e of s.message.content)if("tool_use"===e.type&&e.name===a){const s=e.input;if(s?.file_path&&void 0===s?.offset&&void 0===s?.limit){const o=T(s.file_path,t);i.set(e.id,o)}}else if("tool_use"===e.type&&e.name===l){const s=e.input;if(s?.file_path&&s?.content){const o=T(s.file_path,t);n.set(e.id,{filePath:o,content:s.content})}}else if("tool_use"===e.type&&e.name===r){const s=e.input;if(s?.file_path){const o=T(s.file_path,t);m.set(e.id,o)}}for(const t of e)if("user"===t.type&&Array.isArray(t.message.content))for(const e of t.message.content)if("tool_result"===e.type&&e.tool_use_id){const s=i.get(e.tool_use_id);if(s&&"string"==typeof e.content&&!e.content.startsWith(p)){const i=e.content.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g,"").split("\n").map(d).join("\n").trim();if(t.timestamp){const e=new Date(t.timestamp).getTime();o.set(s,{content:i,timestamp:e,offset:void 0,limit:void 0})}}const r=n.get(e.tool_use_id);if(r&&t.timestamp){const e=new Date(t.timestamp).getTime();o.set(r.filePath,{content:r.content,timestamp:e,offset:void 0,limit:void 0})}const a=m.get(e.tool_use_id);if(a&&!0!==e.is_error)try{const{content:e}=_(a);o.set(a,{content:e,timestamp:u(a),offset:void 0,limit:void 0})}catch(e){if(!f(e))throw e}}return o}export function extractBashToolsFromMessages(e){const t=new Set;for(const s of e)if("assistant"===s.type&&Array.isArray(s.message.content))for(const e of s.message.content)if("tool_use"===e.type&&e.name===n){const{input:s}=e;if("object"!=typeof s||null===s||!("command"in s))continue;const o=extractCliName("string"==typeof s.command?s.command:void 0);o&&t.add(o)}return t}const j=new Set(["sudo"]);function extractCliName(e){if(!e)return;const t=e.trim().split(/\s+/);for(const e of t)if(!/^[A-Za-z_]\w*=/.test(e)&&!j.has(e))return e}