@orion-agents/orion-code 0.1.1 → 0.1.3

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 (643) hide show
  1. package/README.md +165 -68
  2. package/README.zh-CN.md +252 -212
  3. package/dist/cli.js +13 -17
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/index.d.ts.map +1 -1
  6. package/dist/commands/index.js +381 -168
  7. package/dist/commands/index.js.map +1 -1
  8. package/dist/commands/target-command.d.ts.map +1 -1
  9. package/dist/commands/target-command.js +42 -8
  10. package/dist/commands/target-command.js.map +1 -1
  11. package/dist/commands/types.d.ts +3 -1
  12. package/dist/commands/types.d.ts.map +1 -1
  13. package/dist/commands/types.js.map +1 -1
  14. package/dist/core/agent.d.ts.map +1 -1
  15. package/dist/core/agent.js +2 -2
  16. package/dist/core/agent.js.map +1 -1
  17. package/dist/framework/external-assertion.d.ts +65 -0
  18. package/dist/framework/external-assertion.d.ts.map +1 -0
  19. package/dist/framework/external-assertion.js +571 -0
  20. package/dist/framework/external-assertion.js.map +1 -0
  21. package/dist/framework/index.d.ts +6 -4
  22. package/dist/framework/index.d.ts.map +1 -1
  23. package/dist/framework/index.js +4 -1
  24. package/dist/framework/index.js.map +1 -1
  25. package/dist/framework/query.d.ts +18 -1
  26. package/dist/framework/query.d.ts.map +1 -1
  27. package/dist/framework/query.js +43 -23
  28. package/dist/framework/query.js.map +1 -1
  29. package/dist/framework/tool-scheduler.d.ts +63 -1
  30. package/dist/framework/tool-scheduler.d.ts.map +1 -1
  31. package/dist/framework/tool-scheduler.js +183 -51
  32. package/dist/framework/tool-scheduler.js.map +1 -1
  33. package/dist/framework/tool-serializer.d.ts.map +1 -1
  34. package/dist/framework/tool-serializer.js +20 -4
  35. package/dist/framework/tool-serializer.js.map +1 -1
  36. package/dist/framework/tool.d.ts +17 -5
  37. package/dist/framework/tool.d.ts.map +1 -1
  38. package/dist/framework/tool.js +2 -0
  39. package/dist/framework/tool.js.map +1 -1
  40. package/dist/harness/safety.d.ts.map +1 -1
  41. package/dist/harness/safety.js +19 -3
  42. package/dist/harness/safety.js.map +1 -1
  43. package/dist/init.d.ts +1 -1
  44. package/dist/init.d.ts.map +1 -1
  45. package/dist/init.js +115 -34
  46. package/dist/init.js.map +1 -1
  47. package/dist/ink-ui/screens/ReplScreen.d.ts +2 -1
  48. package/dist/ink-ui/screens/ReplScreen.d.ts.map +1 -1
  49. package/dist/ink-ui/screens/ReplScreen.js +65 -0
  50. package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
  51. package/dist/memory/storage.d.ts.map +1 -1
  52. package/dist/memory/storage.js +1 -0
  53. package/dist/memory/storage.js.map +1 -1
  54. package/dist/memory/store.d.ts.map +1 -1
  55. package/dist/memory/store.js +11 -5
  56. package/dist/memory/store.js.map +1 -1
  57. package/dist/print-ui/launch.d.ts +6 -1
  58. package/dist/print-ui/launch.d.ts.map +1 -1
  59. package/dist/print-ui/launch.js +109 -9
  60. package/dist/print-ui/launch.js.map +1 -1
  61. package/dist/product/identity.d.ts +2 -2
  62. package/dist/product/identity.d.ts.map +1 -1
  63. package/dist/product/identity.js +2 -2
  64. package/dist/product/identity.js.map +1 -1
  65. package/dist/product/index.d.ts +2 -1
  66. package/dist/product/index.d.ts.map +1 -1
  67. package/dist/product/index.js +5 -1
  68. package/dist/product/index.js.map +1 -1
  69. package/dist/product/version.d.ts +12 -0
  70. package/dist/product/version.d.ts.map +1 -0
  71. package/dist/product/version.js +31 -0
  72. package/dist/product/version.js.map +1 -0
  73. package/dist/runtime/agent-runtime-controller.d.ts +35 -0
  74. package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
  75. package/dist/runtime/agent-runtime-controller.js +975 -149
  76. package/dist/runtime/agent-runtime-controller.js.map +1 -1
  77. package/dist/runtime/agent-runtime-protocol.d.ts +20 -3
  78. package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
  79. package/dist/runtime/agent-runtime-protocol.js +12 -0
  80. package/dist/runtime/agent-runtime-protocol.js.map +1 -1
  81. package/dist/runtime/chat-controller.d.ts +12 -0
  82. package/dist/runtime/chat-controller.d.ts.map +1 -1
  83. package/dist/runtime/chat-controller.js +213 -19
  84. package/dist/runtime/chat-controller.js.map +1 -1
  85. package/dist/runtime/goals/accounting.d.ts +28 -0
  86. package/dist/runtime/goals/accounting.d.ts.map +1 -1
  87. package/dist/runtime/goals/accounting.js +69 -0
  88. package/dist/runtime/goals/accounting.js.map +1 -1
  89. package/dist/runtime/goals/completion-audit.d.ts +13 -8
  90. package/dist/runtime/goals/completion-audit.d.ts.map +1 -1
  91. package/dist/runtime/goals/completion-audit.js +598 -16
  92. package/dist/runtime/goals/completion-audit.js.map +1 -1
  93. package/dist/runtime/goals/coordinator.d.ts +44 -5
  94. package/dist/runtime/goals/coordinator.d.ts.map +1 -1
  95. package/dist/runtime/goals/coordinator.js +1124 -58
  96. package/dist/runtime/goals/coordinator.js.map +1 -1
  97. package/dist/runtime/goals/evidence.d.ts +37 -0
  98. package/dist/runtime/goals/evidence.d.ts.map +1 -0
  99. package/dist/runtime/goals/evidence.js +300 -0
  100. package/dist/runtime/goals/evidence.js.map +1 -0
  101. package/dist/runtime/goals/presentation.d.ts +4 -0
  102. package/dist/runtime/goals/presentation.d.ts.map +1 -0
  103. package/dist/runtime/goals/presentation.js +50 -0
  104. package/dist/runtime/goals/presentation.js.map +1 -0
  105. package/dist/runtime/goals/prompt.d.ts.map +1 -1
  106. package/dist/runtime/goals/prompt.js +38 -8
  107. package/dist/runtime/goals/prompt.js.map +1 -1
  108. package/dist/runtime/goals/tools.d.ts +18 -1
  109. package/dist/runtime/goals/tools.d.ts.map +1 -1
  110. package/dist/runtime/goals/tools.js +310 -30
  111. package/dist/runtime/goals/tools.js.map +1 -1
  112. package/dist/runtime/goals/types.d.ts +247 -7
  113. package/dist/runtime/goals/types.d.ts.map +1 -1
  114. package/dist/runtime/goals/types.js +8 -2
  115. package/dist/runtime/goals/types.js.map +1 -1
  116. package/dist/runtime/subagents/child-executor-guard.d.ts +12 -4
  117. package/dist/runtime/subagents/child-executor-guard.d.ts.map +1 -1
  118. package/dist/runtime/subagents/child-executor-guard.js +397 -61
  119. package/dist/runtime/subagents/child-executor-guard.js.map +1 -1
  120. package/dist/runtime/subagents/presets.d.ts +4 -5
  121. package/dist/runtime/subagents/presets.d.ts.map +1 -1
  122. package/dist/runtime/subagents/presets.js +18 -33
  123. package/dist/runtime/subagents/presets.js.map +1 -1
  124. package/dist/runtime/subagents/production.d.ts +3 -1
  125. package/dist/runtime/subagents/production.d.ts.map +1 -1
  126. package/dist/runtime/subagents/production.js +37 -7
  127. package/dist/runtime/subagents/production.js.map +1 -1
  128. package/dist/runtime/subagents/runner.d.ts.map +1 -1
  129. package/dist/runtime/subagents/runner.js +24 -3
  130. package/dist/runtime/subagents/runner.js.map +1 -1
  131. package/dist/runtime/subagents/runtime-integration.d.ts +3 -0
  132. package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -1
  133. package/dist/runtime/subagents/runtime-integration.js +18 -7
  134. package/dist/runtime/subagents/runtime-integration.js.map +1 -1
  135. package/dist/runtime/subagents/supervisor.d.ts +4 -4
  136. package/dist/runtime/subagents/supervisor.d.ts.map +1 -1
  137. package/dist/runtime/subagents/supervisor.js +39 -19
  138. package/dist/runtime/subagents/supervisor.js.map +1 -1
  139. package/dist/runtime/subagents/types.d.ts +7 -0
  140. package/dist/runtime/subagents/types.d.ts.map +1 -1
  141. package/dist/runtime/subagents/types.js +12 -1
  142. package/dist/runtime/subagents/types.js.map +1 -1
  143. package/dist/runtime/turn-controller.d.ts.map +1 -1
  144. package/dist/runtime/turn-controller.js +3 -1
  145. package/dist/runtime/turn-controller.js.map +1 -1
  146. package/dist/runtime/ui-events.d.ts +23 -0
  147. package/dist/runtime/ui-events.d.ts.map +1 -1
  148. package/dist/runtime/ui-events.js +5 -5
  149. package/dist/runtime/ui-events.js.map +1 -1
  150. package/dist/services/config.d.ts +1 -1
  151. package/dist/services/config.d.ts.map +1 -1
  152. package/dist/services/config.js +55 -49
  153. package/dist/services/config.js.map +1 -1
  154. package/dist/services/doctor.d.ts.map +1 -1
  155. package/dist/services/doctor.js +163 -17
  156. package/dist/services/doctor.js.map +1 -1
  157. package/dist/services/global-config.d.ts +31 -0
  158. package/dist/services/global-config.d.ts.map +1 -1
  159. package/dist/services/global-config.js.map +1 -1
  160. package/dist/services/goal-storage.d.ts +9 -4
  161. package/dist/services/goal-storage.d.ts.map +1 -1
  162. package/dist/services/goal-storage.js +1113 -75
  163. package/dist/services/goal-storage.js.map +1 -1
  164. package/dist/services/llm.d.ts +19 -0
  165. package/dist/services/llm.d.ts.map +1 -1
  166. package/dist/services/llm.js +153 -20
  167. package/dist/services/llm.js.map +1 -1
  168. package/dist/services/model-catalog.d.ts +2 -0
  169. package/dist/services/model-catalog.d.ts.map +1 -1
  170. package/dist/services/model-catalog.js +25 -15
  171. package/dist/services/model-catalog.js.map +1 -1
  172. package/dist/services/model-context.d.ts.map +1 -1
  173. package/dist/services/model-context.js +36 -0
  174. package/dist/services/model-context.js.map +1 -1
  175. package/dist/services/model-registry.d.ts +1 -1
  176. package/dist/services/model-registry.d.ts.map +1 -1
  177. package/dist/services/model-registry.js +101 -19
  178. package/dist/services/model-registry.js.map +1 -1
  179. package/dist/services/provider-resilience/coordinator.d.ts +2 -1
  180. package/dist/services/provider-resilience/coordinator.d.ts.map +1 -1
  181. package/dist/services/provider-resilience/coordinator.js +7 -6
  182. package/dist/services/provider-resilience/coordinator.js.map +1 -1
  183. package/dist/services/provider-resilience/error-classifier.d.ts.map +1 -1
  184. package/dist/services/provider-resilience/error-classifier.js +67 -17
  185. package/dist/services/provider-resilience/error-classifier.js.map +1 -1
  186. package/dist/services/provider-resilience/types.d.ts +1 -1
  187. package/dist/services/provider-resilience/types.d.ts.map +1 -1
  188. package/dist/services/provider-resilience/types.js.map +1 -1
  189. package/dist/services/redaction.d.ts.map +1 -1
  190. package/dist/services/redaction.js +9 -1
  191. package/dist/services/redaction.js.map +1 -1
  192. package/dist/services/session-storage.d.ts +12 -1
  193. package/dist/services/session-storage.d.ts.map +1 -1
  194. package/dist/services/session-storage.js +23 -7
  195. package/dist/services/session-storage.js.map +1 -1
  196. package/dist/services/storage-maintenance.d.ts +73 -3
  197. package/dist/services/storage-maintenance.d.ts.map +1 -1
  198. package/dist/services/storage-maintenance.js +771 -104
  199. package/dist/services/storage-maintenance.js.map +1 -1
  200. package/dist/services/task-manager.d.ts.map +1 -1
  201. package/dist/services/task-manager.js +2 -2
  202. package/dist/services/task-manager.js.map +1 -1
  203. package/dist/services/tool-allowlist.d.ts +100 -0
  204. package/dist/services/tool-allowlist.d.ts.map +1 -0
  205. package/dist/services/tool-allowlist.js +250 -0
  206. package/dist/services/tool-allowlist.js.map +1 -0
  207. package/dist/services/web-search-adapters.d.ts.map +1 -1
  208. package/dist/services/web-search-adapters.js +89 -49
  209. package/dist/services/web-search-adapters.js.map +1 -1
  210. package/dist/services/web-search-mcp.d.ts.map +1 -1
  211. package/dist/services/web-search-mcp.js +34 -37
  212. package/dist/services/web-search-mcp.js.map +1 -1
  213. package/dist/services/workspace-state.d.ts +4 -0
  214. package/dist/services/workspace-state.d.ts.map +1 -1
  215. package/dist/services/workspace-state.js +30 -9
  216. package/dist/services/workspace-state.js.map +1 -1
  217. package/dist/terminal-ui/launch.d.ts +24 -2
  218. package/dist/terminal-ui/launch.d.ts.map +1 -1
  219. package/dist/terminal-ui/launch.js +166 -8
  220. package/dist/terminal-ui/launch.js.map +1 -1
  221. package/dist/tools/git.d.ts +4 -0
  222. package/dist/tools/git.d.ts.map +1 -1
  223. package/dist/tools/git.js +585 -30
  224. package/dist/tools/git.js.map +1 -1
  225. package/dist/tools/index.d.ts.map +1 -1
  226. package/dist/tools/index.js +79 -11
  227. package/dist/tools/index.js.map +1 -1
  228. package/dist/tools/mcp.d.ts.map +1 -1
  229. package/dist/tools/mcp.js +20 -12
  230. package/dist/tools/mcp.js.map +1 -1
  231. package/dist/tools/sandbox.d.ts +139 -0
  232. package/dist/tools/sandbox.d.ts.map +1 -0
  233. package/dist/tools/sandbox.js +485 -0
  234. package/dist/tools/sandbox.js.map +1 -0
  235. package/dist/tools/web.d.ts.map +1 -1
  236. package/dist/tools/web.js +149 -54
  237. package/dist/tools/web.js.map +1 -1
  238. package/dist/tui-ui/launch.d.ts.map +1 -1
  239. package/dist/tui-ui/launch.js +46 -8
  240. package/dist/tui-ui/launch.js.map +1 -1
  241. package/dist/tui-ui/layout.d.ts.map +1 -1
  242. package/dist/tui-ui/layout.js +98 -23
  243. package/dist/tui-ui/layout.js.map +1 -1
  244. package/dist/tui-ui/pickers.d.ts.map +1 -1
  245. package/dist/tui-ui/pickers.js +4 -3
  246. package/dist/tui-ui/pickers.js.map +1 -1
  247. package/dist/tui-ui/runner.d.ts +7 -0
  248. package/dist/tui-ui/runner.d.ts.map +1 -1
  249. package/dist/tui-ui/runner.js +95 -1
  250. package/dist/tui-ui/runner.js.map +1 -1
  251. package/dist/tui-ui/state.d.ts +25 -1
  252. package/dist/tui-ui/state.d.ts.map +1 -1
  253. package/dist/tui-ui/state.js +95 -37
  254. package/dist/tui-ui/state.js.map +1 -1
  255. package/dist/tui-ui/terminal-image.d.ts +3 -13
  256. package/dist/tui-ui/terminal-image.d.ts.map +1 -1
  257. package/dist/tui-ui/terminal-image.js +5 -160
  258. package/dist/tui-ui/terminal-image.js.map +1 -1
  259. package/dist/utils/mask.d.ts +28 -0
  260. package/dist/utils/mask.d.ts.map +1 -0
  261. package/dist/utils/mask.js +54 -0
  262. package/dist/utils/mask.js.map +1 -0
  263. package/package.json +14 -9
  264. package/dist/core/state.d.ts +0 -94
  265. package/dist/core/state.d.ts.map +0 -1
  266. package/dist/core/state.js +0 -178
  267. package/dist/core/state.js.map +0 -1
  268. package/dist/ink/bidi.d.ts +0 -16
  269. package/dist/ink/bidi.d.ts.map +0 -1
  270. package/dist/ink/bidi.js +0 -124
  271. package/dist/ink/bidi.js.map +0 -1
  272. package/dist/ink/clearTerminal.d.ts +0 -14
  273. package/dist/ink/clearTerminal.d.ts.map +0 -1
  274. package/dist/ink/clearTerminal.js +0 -63
  275. package/dist/ink/clearTerminal.js.map +0 -1
  276. package/dist/ink/colorize.d.ts +0 -17
  277. package/dist/ink/colorize.d.ts.map +0 -1
  278. package/dist/ink/colorize.js +0 -208
  279. package/dist/ink/colorize.js.map +0 -1
  280. package/dist/ink/components/App.d.ts +0 -73
  281. package/dist/ink/components/App.d.ts.map +0 -1
  282. package/dist/ink/components/App.js +0 -646
  283. package/dist/ink/components/App.js.map +0 -1
  284. package/dist/ink/components/AppContext.d.ts +0 -12
  285. package/dist/ink/components/AppContext.d.ts.map +0 -1
  286. package/dist/ink/components/AppContext.js +0 -14
  287. package/dist/ink/components/AppContext.js.map +0 -1
  288. package/dist/ink/components/Box.d.ts +0 -44
  289. package/dist/ink/components/Box.d.ts.map +0 -1
  290. package/dist/ink/components/Box.js +0 -191
  291. package/dist/ink/components/Box.js.map +0 -1
  292. package/dist/ink/components/ClockContext.d.ts +0 -9
  293. package/dist/ink/components/ClockContext.d.ts.map +0 -1
  294. package/dist/ink/components/ClockContext.js +0 -146
  295. package/dist/ink/components/ClockContext.js.map +0 -1
  296. package/dist/ink/components/CursorDeclarationContext.d.ts +0 -23
  297. package/dist/ink/components/CursorDeclarationContext.d.ts.map +0 -1
  298. package/dist/ink/components/CursorDeclarationContext.js +0 -6
  299. package/dist/ink/components/CursorDeclarationContext.js.map +0 -1
  300. package/dist/ink/components/ErrorOverview.d.ts +0 -6
  301. package/dist/ink/components/ErrorOverview.d.ts.map +0 -1
  302. package/dist/ink/components/ErrorOverview.js +0 -27
  303. package/dist/ink/components/ErrorOverview.js.map +0 -1
  304. package/dist/ink/components/Newline.d.ts +0 -13
  305. package/dist/ink/components/Newline.d.ts.map +0 -1
  306. package/dist/ink/components/Newline.js +0 -36
  307. package/dist/ink/components/Newline.js.map +0 -1
  308. package/dist/ink/components/NoSelect.d.ts +0 -20
  309. package/dist/ink/components/NoSelect.d.ts.map +0 -1
  310. package/dist/ink/components/NoSelect.js +0 -63
  311. package/dist/ink/components/NoSelect.js.map +0 -1
  312. package/dist/ink/components/RawAnsi.d.ts +0 -17
  313. package/dist/ink/components/RawAnsi.d.ts.map +0 -1
  314. package/dist/ink/components/RawAnsi.js +0 -52
  315. package/dist/ink/components/RawAnsi.js.map +0 -1
  316. package/dist/ink/components/Spacer.d.ts +0 -6
  317. package/dist/ink/components/Spacer.d.ts.map +0 -1
  318. package/dist/ink/components/Spacer.js +0 -26
  319. package/dist/ink/components/Spacer.js.map +0 -1
  320. package/dist/ink/components/StdinContext.d.ts +0 -28
  321. package/dist/ink/components/StdinContext.d.ts.map +0 -1
  322. package/dist/ink/components/StdinContext.js +0 -19
  323. package/dist/ink/components/StdinContext.js.map +0 -1
  324. package/dist/ink/components/TerminalFocusContext.d.ts +0 -10
  325. package/dist/ink/components/TerminalFocusContext.d.ts.map +0 -1
  326. package/dist/ink/components/TerminalFocusContext.js +0 -81
  327. package/dist/ink/components/TerminalFocusContext.js.map +0 -1
  328. package/dist/ink/components/TerminalSizeContext.d.ts +0 -6
  329. package/dist/ink/components/TerminalSizeContext.d.ts.map +0 -1
  330. package/dist/ink/components/TerminalSizeContext.js +0 -6
  331. package/dist/ink/components/TerminalSizeContext.js.map +0 -1
  332. package/dist/ink/components/Text.d.ts +0 -56
  333. package/dist/ink/components/Text.d.ts.map +0 -1
  334. package/dist/ink/components/Text.js +0 -201
  335. package/dist/ink/components/Text.js.map +0 -1
  336. package/dist/ink/constants.d.ts +0 -2
  337. package/dist/ink/constants.d.ts.map +0 -1
  338. package/dist/ink/constants.js +0 -6
  339. package/dist/ink/constants.js.map +0 -1
  340. package/dist/ink/devtools.d.ts +0 -3
  341. package/dist/ink/devtools.d.ts.map +0 -1
  342. package/dist/ink/devtools.js +0 -5
  343. package/dist/ink/devtools.js.map +0 -1
  344. package/dist/ink/dom.d.ts +0 -77
  345. package/dist/ink/dom.d.ts.map +0 -1
  346. package/dist/ink/dom.js +0 -322
  347. package/dist/ink/dom.js.map +0 -1
  348. package/dist/ink/events/click-event.d.ts +0 -32
  349. package/dist/ink/events/click-event.d.ts.map +0 -1
  350. package/dist/ink/events/click-event.js +0 -30
  351. package/dist/ink/events/click-event.js.map +0 -1
  352. package/dist/ink/events/dispatcher.d.ts +0 -41
  353. package/dist/ink/events/dispatcher.d.ts.map +0 -1
  354. package/dist/ink/events/dispatcher.js +0 -181
  355. package/dist/ink/events/dispatcher.js.map +0 -1
  356. package/dist/ink/events/emitter.d.ts +0 -6
  357. package/dist/ink/events/emitter.d.ts.map +0 -1
  358. package/dist/ink/events/emitter.js +0 -36
  359. package/dist/ink/events/emitter.js.map +0 -1
  360. package/dist/ink/events/event-handlers.d.ts +0 -47
  361. package/dist/ink/events/event-handlers.d.ts.map +0 -1
  362. package/dist/ink/events/event-handlers.js +0 -34
  363. package/dist/ink/events/event-handlers.js.map +0 -1
  364. package/dist/ink/events/event.d.ts +0 -6
  365. package/dist/ink/events/event.d.ts.map +0 -1
  366. package/dist/ink/events/event.js +0 -16
  367. package/dist/ink/events/event.js.map +0 -1
  368. package/dist/ink/events/focus-event.d.ts +0 -14
  369. package/dist/ink/events/focus-event.d.ts.map +0 -1
  370. package/dist/ink/events/focus-event.js +0 -20
  371. package/dist/ink/events/focus-event.js.map +0 -1
  372. package/dist/ink/events/input-event.d.ts +0 -31
  373. package/dist/ink/events/input-event.d.ts.map +0 -1
  374. package/dist/ink/events/input-event.js +0 -163
  375. package/dist/ink/events/input-event.js.map +0 -1
  376. package/dist/ink/events/keyboard-event.d.ts +0 -20
  377. package/dist/ink/events/keyboard-event.d.ts.map +0 -1
  378. package/dist/ink/events/keyboard-event.js +0 -44
  379. package/dist/ink/events/keyboard-event.js.map +0 -1
  380. package/dist/ink/events/terminal-event.d.ts +0 -55
  381. package/dist/ink/events/terminal-event.d.ts.map +0 -1
  382. package/dist/ink/events/terminal-event.js +0 -79
  383. package/dist/ink/events/terminal-event.js.map +0 -1
  384. package/dist/ink/events/terminal-focus-event.d.ts +0 -14
  385. package/dist/ink/events/terminal-focus-event.d.ts.map +0 -1
  386. package/dist/ink/events/terminal-focus-event.js +0 -19
  387. package/dist/ink/events/terminal-focus-event.js.map +0 -1
  388. package/dist/ink/focus.d.ts +0 -44
  389. package/dist/ink/focus.d.ts.map +0 -1
  390. package/dist/ink/focus.js +0 -164
  391. package/dist/ink/focus.js.map +0 -1
  392. package/dist/ink/frame.d.ts +0 -95
  393. package/dist/ink/frame.d.ts.map +0 -1
  394. package/dist/ink/frame.js +0 -35
  395. package/dist/ink/frame.js.map +0 -1
  396. package/dist/ink/get-max-width.d.ts +0 -18
  397. package/dist/ink/get-max-width.d.ts.map +0 -1
  398. package/dist/ink/get-max-width.js +0 -26
  399. package/dist/ink/get-max-width.js.map +0 -1
  400. package/dist/ink/hit-test.d.ts +0 -34
  401. package/dist/ink/hit-test.d.ts.map +0 -1
  402. package/dist/ink/hit-test.js +0 -119
  403. package/dist/ink/hit-test.js.map +0 -1
  404. package/dist/ink/hooks/use-animation-frame.d.ts +0 -27
  405. package/dist/ink/hooks/use-animation-frame.d.ts.map +0 -1
  406. package/dist/ink/hooks/use-animation-frame.js +0 -52
  407. package/dist/ink/hooks/use-animation-frame.js.map +0 -1
  408. package/dist/ink/hooks/use-app.d.ts +0 -6
  409. package/dist/ink/hooks/use-app.d.ts.map +0 -1
  410. package/dist/ink/hooks/use-app.js +0 -13
  411. package/dist/ink/hooks/use-app.js.map +0 -1
  412. package/dist/ink/hooks/use-declared-cursor.d.ts +0 -27
  413. package/dist/ink/hooks/use-declared-cursor.d.ts.map +0 -1
  414. package/dist/ink/hooks/use-declared-cursor.js +0 -67
  415. package/dist/ink/hooks/use-declared-cursor.js.map +0 -1
  416. package/dist/ink/hooks/use-input.d.ts +0 -38
  417. package/dist/ink/hooks/use-input.d.ts.map +0 -1
  418. package/dist/ink/hooks/use-input.js +0 -86
  419. package/dist/ink/hooks/use-input.js.map +0 -1
  420. package/dist/ink/hooks/use-interval.d.ts +0 -19
  421. package/dist/ink/hooks/use-interval.d.ts.map +0 -1
  422. package/dist/ink/hooks/use-interval.js +0 -59
  423. package/dist/ink/hooks/use-interval.js.map +0 -1
  424. package/dist/ink/hooks/use-search-highlight.d.ts +0 -31
  425. package/dist/ink/hooks/use-search-highlight.d.ts.map +0 -1
  426. package/dist/ink/hooks/use-search-highlight.js +0 -39
  427. package/dist/ink/hooks/use-search-highlight.js.map +0 -1
  428. package/dist/ink/hooks/use-selection.d.ts +0 -40
  429. package/dist/ink/hooks/use-selection.d.ts.map +0 -1
  430. package/dist/ink/hooks/use-selection.js +0 -68
  431. package/dist/ink/hooks/use-selection.js.map +0 -1
  432. package/dist/ink/hooks/use-stdin.d.ts +0 -6
  433. package/dist/ink/hooks/use-stdin.d.ts.map +0 -1
  434. package/dist/ink/hooks/use-stdin.js +0 -13
  435. package/dist/ink/hooks/use-stdin.js.map +0 -1
  436. package/dist/ink/hooks/use-tab-status.d.ts +0 -14
  437. package/dist/ink/hooks/use-tab-status.d.ts.map +0 -1
  438. package/dist/ink/hooks/use-tab-status.js +0 -61
  439. package/dist/ink/hooks/use-tab-status.js.map +0 -1
  440. package/dist/ink/hooks/use-terminal-focus.d.ts +0 -11
  441. package/dist/ink/hooks/use-terminal-focus.d.ts.map +0 -1
  442. package/dist/ink/hooks/use-terminal-focus.js +0 -22
  443. package/dist/ink/hooks/use-terminal-focus.js.map +0 -1
  444. package/dist/ink/hooks/use-terminal-title.d.ts +0 -13
  445. package/dist/ink/hooks/use-terminal-title.d.ts.map +0 -1
  446. package/dist/ink/hooks/use-terminal-title.js +0 -36
  447. package/dist/ink/hooks/use-terminal-title.js.map +0 -1
  448. package/dist/ink/hooks/use-terminal-viewport.d.ts +0 -30
  449. package/dist/ink/hooks/use-terminal-viewport.d.ts.map +0 -1
  450. package/dist/ink/hooks/use-terminal-viewport.js +0 -81
  451. package/dist/ink/hooks/use-terminal-viewport.js.map +0 -1
  452. package/dist/ink/ink.d.ts +0 -371
  453. package/dist/ink/ink.d.ts.map +0 -1
  454. package/dist/ink/ink.js +0 -1686
  455. package/dist/ink/ink.js.map +0 -1
  456. package/dist/ink/instances.d.ts +0 -4
  457. package/dist/ink/instances.d.ts.map +0 -1
  458. package/dist/ink/instances.js +0 -10
  459. package/dist/ink/instances.js.map +0 -1
  460. package/dist/ink/line-width-cache.d.ts +0 -2
  461. package/dist/ink/line-width-cache.d.ts.map +0 -1
  462. package/dist/ink/line-width-cache.js +0 -23
  463. package/dist/ink/line-width-cache.js.map +0 -1
  464. package/dist/ink/log-update.d.ts +0 -18
  465. package/dist/ink/log-update.d.ts.map +0 -1
  466. package/dist/ink/log-update.js +0 -637
  467. package/dist/ink/log-update.js.map +0 -1
  468. package/dist/ink/measure-element.d.ts +0 -17
  469. package/dist/ink/measure-element.d.ts.map +0 -1
  470. package/dist/ink/measure-element.js +0 -11
  471. package/dist/ink/measure-element.js.map +0 -1
  472. package/dist/ink/measure-text.d.ts +0 -7
  473. package/dist/ink/measure-text.d.ts.map +0 -1
  474. package/dist/ink/measure-text.js +0 -38
  475. package/dist/ink/measure-text.js.map +0 -1
  476. package/dist/ink/node-cache.d.ts +0 -21
  477. package/dist/ink/node-cache.d.ts.map +0 -1
  478. package/dist/ink/node-cache.js +0 -36
  479. package/dist/ink/node-cache.js.map +0 -1
  480. package/dist/ink/optimizer.d.ts +0 -16
  481. package/dist/ink/optimizer.d.ts.map +0 -1
  482. package/dist/ink/optimizer.js +0 -85
  483. package/dist/ink/optimizer.js.map +0 -1
  484. package/dist/ink/output.d.ts +0 -120
  485. package/dist/ink/output.d.ts.map +0 -1
  486. package/dist/ink/output.js +0 -559
  487. package/dist/ink/output.js.map +0 -1
  488. package/dist/ink/parse-keypress.d.ts +0 -112
  489. package/dist/ink/parse-keypress.d.ts.map +0 -1
  490. package/dist/ink/parse-keypress.js +0 -719
  491. package/dist/ink/parse-keypress.js.map +0 -1
  492. package/dist/ink/parse-keypress.test.d.ts +0 -2
  493. package/dist/ink/parse-keypress.test.d.ts.map +0 -1
  494. package/dist/ink/parse-keypress.test.js +0 -37
  495. package/dist/ink/parse-keypress.test.js.map +0 -1
  496. package/dist/ink/reconciler.d.ts +0 -12
  497. package/dist/ink/reconciler.d.ts.map +0 -1
  498. package/dist/ink/reconciler.js +0 -456
  499. package/dist/ink/reconciler.js.map +0 -1
  500. package/dist/ink/render-border.d.ts +0 -25
  501. package/dist/ink/render-border.d.ts.map +0 -1
  502. package/dist/ink/render-border.js +0 -141
  503. package/dist/ink/render-border.js.map +0 -1
  504. package/dist/ink/render-node-to-output.d.ts +0 -46
  505. package/dist/ink/render-node-to-output.d.ts.map +0 -1
  506. package/dist/ink/render-node-to-output.js +0 -1257
  507. package/dist/ink/render-node-to-output.js.map +0 -1
  508. package/dist/ink/render-to-screen.d.ts +0 -47
  509. package/dist/ink/render-to-screen.d.ts.map +0 -1
  510. package/dist/ink/render-to-screen.js +0 -213
  511. package/dist/ink/render-to-screen.js.map +0 -1
  512. package/dist/ink/renderer.d.ts +0 -15
  513. package/dist/ink/renderer.d.ts.map +0 -1
  514. package/dist/ink/renderer.js +0 -169
  515. package/dist/ink/renderer.js.map +0 -1
  516. package/dist/ink/root.d.ts +0 -75
  517. package/dist/ink/root.d.ts.map +0 -1
  518. package/dist/ink/root.js +0 -89
  519. package/dist/ink/root.js.map +0 -1
  520. package/dist/ink/screen.d.ts +0 -270
  521. package/dist/ink/screen.d.ts.map +0 -1
  522. package/dist/ink/screen.js +0 -1194
  523. package/dist/ink/screen.js.map +0 -1
  524. package/dist/ink/searchHighlight.d.ts +0 -21
  525. package/dist/ink/searchHighlight.d.ts.map +0 -1
  526. package/dist/ink/searchHighlight.js +0 -82
  527. package/dist/ink/searchHighlight.js.map +0 -1
  528. package/dist/ink/selection.d.ts +0 -230
  529. package/dist/ink/selection.d.ts.map +0 -1
  530. package/dist/ink/selection.js +0 -814
  531. package/dist/ink/selection.js.map +0 -1
  532. package/dist/ink/squash-text-nodes.d.ts +0 -23
  533. package/dist/ink/squash-text-nodes.d.ts.map +0 -1
  534. package/dist/ink/squash-text-nodes.js +0 -60
  535. package/dist/ink/squash-text-nodes.js.map +0 -1
  536. package/dist/ink/stringWidth.d.ts +0 -2
  537. package/dist/ink/stringWidth.d.ts.map +0 -1
  538. package/dist/ink/stringWidth.js +0 -207
  539. package/dist/ink/stringWidth.js.map +0 -1
  540. package/dist/ink/styles.d.ts +0 -307
  541. package/dist/ink/styles.d.ts.map +0 -1
  542. package/dist/ink/styles.js +0 -302
  543. package/dist/ink/styles.js.map +0 -1
  544. package/dist/ink/supports-hyperlinks.d.ts +0 -14
  545. package/dist/ink/supports-hyperlinks.d.ts.map +0 -1
  546. package/dist/ink/supports-hyperlinks.js +0 -48
  547. package/dist/ink/supports-hyperlinks.js.map +0 -1
  548. package/dist/ink/tabstops.d.ts +0 -2
  549. package/dist/ink/tabstops.d.ts.map +0 -1
  550. package/dist/ink/tabstops.js +0 -43
  551. package/dist/ink/tabstops.js.map +0 -1
  552. package/dist/ink/terminal-focus-state.d.ts +0 -7
  553. package/dist/ink/terminal-focus-state.d.ts.map +0 -1
  554. package/dist/ink/terminal-focus-state.js +0 -43
  555. package/dist/ink/terminal-focus-state.js.map +0 -1
  556. package/dist/ink/terminal-querier.d.ts +0 -130
  557. package/dist/ink/terminal-querier.d.ts.map +0 -1
  558. package/dist/ink/terminal-querier.js +0 -184
  559. package/dist/ink/terminal-querier.js.map +0 -1
  560. package/dist/ink/terminal.d.ts +0 -56
  561. package/dist/ink/terminal.d.ts.map +0 -1
  562. package/dist/ink/terminal.js +0 -249
  563. package/dist/ink/terminal.js.map +0 -1
  564. package/dist/ink/termio/csi.d.ts +0 -166
  565. package/dist/ink/termio/csi.d.ts.map +0 -1
  566. package/dist/ink/termio/csi.js +0 -285
  567. package/dist/ink/termio/csi.js.map +0 -1
  568. package/dist/ink/termio/dec.d.ts +0 -38
  569. package/dist/ink/termio/dec.d.ts.map +0 -1
  570. package/dist/ink/termio/dec.js +0 -59
  571. package/dist/ink/termio/dec.js.map +0 -1
  572. package/dist/ink/termio.d.ts +0 -25
  573. package/dist/ink/termio.d.ts.map +0 -1
  574. package/dist/ink/termio.js +0 -32
  575. package/dist/ink/termio.js.map +0 -1
  576. package/dist/ink/useTerminalNotification.d.ts +0 -27
  577. package/dist/ink/useTerminalNotification.d.ts.map +0 -1
  578. package/dist/ink/useTerminalNotification.js +0 -62
  579. package/dist/ink/useTerminalNotification.js.map +0 -1
  580. package/dist/ink/warn.d.ts +0 -2
  581. package/dist/ink/warn.d.ts.map +0 -1
  582. package/dist/ink/warn.js +0 -14
  583. package/dist/ink/warn.js.map +0 -1
  584. package/dist/ink/widest-line.d.ts +0 -2
  585. package/dist/ink/widest-line.d.ts.map +0 -1
  586. package/dist/ink/widest-line.js +0 -18
  587. package/dist/ink/widest-line.js.map +0 -1
  588. package/dist/ink/wrap-text.d.ts +0 -3
  589. package/dist/ink/wrap-text.d.ts.map +0 -1
  590. package/dist/ink/wrap-text.js +0 -61
  591. package/dist/ink/wrap-text.js.map +0 -1
  592. package/dist/ink/wrapAnsi.d.ts +0 -8
  593. package/dist/ink/wrapAnsi.d.ts.map +0 -1
  594. package/dist/ink/wrapAnsi.js +0 -13
  595. package/dist/ink/wrapAnsi.js.map +0 -1
  596. package/dist/ink-ui/components/TerminalCursor.d.ts +0 -15
  597. package/dist/ink-ui/components/TerminalCursor.d.ts.map +0 -1
  598. package/dist/ink-ui/components/TerminalCursor.js +0 -49
  599. package/dist/ink-ui/components/TerminalCursor.js.map +0 -1
  600. package/dist/ink-ui/runtime/stdout.d.ts +0 -11
  601. package/dist/ink-ui/runtime/stdout.d.ts.map +0 -1
  602. package/dist/ink-ui/runtime/stdout.js +0 -82
  603. package/dist/ink-ui/runtime/stdout.js.map +0 -1
  604. package/dist/runtime/goal-coordinator.d.ts +0 -66
  605. package/dist/runtime/goal-coordinator.d.ts.map +0 -1
  606. package/dist/runtime/goal-coordinator.js +0 -200
  607. package/dist/runtime/goal-coordinator.js.map +0 -1
  608. package/dist/screens/REPL.d.ts +0 -21
  609. package/dist/screens/REPL.d.ts.map +0 -1
  610. package/dist/screens/REPL.js +0 -139
  611. package/dist/screens/REPL.js.map +0 -1
  612. package/dist/services/goal-sidecar.d.ts +0 -96
  613. package/dist/services/goal-sidecar.d.ts.map +0 -1
  614. package/dist/services/goal-sidecar.js +0 -145
  615. package/dist/services/goal-sidecar.js.map +0 -1
  616. package/dist/tools/goal.d.ts +0 -17
  617. package/dist/tools/goal.d.ts.map +0 -1
  618. package/dist/tools/goal.js +0 -191
  619. package/dist/tools/goal.js.map +0 -1
  620. package/dist/ui/ink/components/App.d.ts +0 -6
  621. package/dist/ui/ink/components/App.d.ts.map +0 -1
  622. package/dist/ui/ink/components/App.js +0 -38
  623. package/dist/ui/ink/components/App.js.map +0 -1
  624. package/dist/ui/ink/components/CommandPanel.d.ts +0 -13
  625. package/dist/ui/ink/components/CommandPanel.d.ts.map +0 -1
  626. package/dist/ui/ink/components/CommandPanel.js +0 -41
  627. package/dist/ui/ink/components/CommandPanel.js.map +0 -1
  628. package/dist/ui/ink/components/InputLine.d.ts +0 -8
  629. package/dist/ui/ink/components/InputLine.d.ts.map +0 -1
  630. package/dist/ui/ink/components/InputLine.js +0 -15
  631. package/dist/ui/ink/components/InputLine.js.map +0 -1
  632. package/dist/ui/ink/components/StatusBar.d.ts +0 -9
  633. package/dist/ui/ink/components/StatusBar.d.ts.map +0 -1
  634. package/dist/ui/ink/components/StatusBar.js +0 -18
  635. package/dist/ui/ink/components/StatusBar.js.map +0 -1
  636. package/dist/ui/ink/components/index.d.ts +0 -5
  637. package/dist/ui/ink/components/index.d.ts.map +0 -1
  638. package/dist/ui/ink/components/index.js +0 -5
  639. package/dist/ui/ink/components/index.js.map +0 -1
  640. package/dist/utils/chalk.d.ts +0 -9
  641. package/dist/utils/chalk.d.ts.map +0 -1
  642. package/dist/utils/chalk.js +0 -16
  643. package/dist/utils/chalk.js.map +0 -1
package/dist/tools/git.js CHANGED
@@ -10,21 +10,43 @@
10
10
  * - git_push: 安全推送(验证 + commit)
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.GIT_TOOLS = exports.gitPushTool = exports.gitStatusTool = void 0;
13
+ exports.GIT_TOOLS = exports.gitBranchTool = exports.gitLogTool = exports.gitDiffTool = exports.gitCommitTool = exports.gitPushTool = exports.gitStatusTool = void 0;
14
14
  const tool_1 = require("../framework/tool");
15
15
  const child_process_1 = require("child_process");
16
+ const path_1 = require("path");
17
+ function normalizeStagePath(value) {
18
+ if (value.length === 0 ||
19
+ value.includes('\0') ||
20
+ value.includes('\r') ||
21
+ value.includes('\n') ||
22
+ value.includes('\\') ||
23
+ value.startsWith('/') ||
24
+ value.startsWith(':') ||
25
+ ['*', '?', '[', ']'].some(character => value.includes(character))) {
26
+ return null;
27
+ }
28
+ const normalized = path_1.posix.normalize(value);
29
+ if (normalized === '.' || normalized === '..' || normalized.startsWith('../')) {
30
+ return null;
31
+ }
32
+ return normalized;
33
+ }
34
+ function parseStagedPaths(output) {
35
+ return output.split('\0').filter(Boolean);
36
+ }
16
37
  async function execGit(command, cwd, timeout = 30000) {
17
38
  return execGitArgs(command.split(' '), cwd, timeout);
18
39
  }
19
40
  async function execGitArgs(args, cwd, timeout = 30000) {
20
- return new Promise((resolve) => {
41
+ return new Promise(resolve => {
21
42
  const workdir = cwd || process.cwd();
22
43
  (0, child_process_1.execFile)('git', args, {
23
44
  cwd: workdir,
24
45
  timeout,
25
46
  maxBuffer: 1024 * 1024,
26
47
  }, (error, stdout, stderr) => {
27
- const output = stdout.toString().trim();
48
+ // Preserve the leading status columns from `git status --porcelain`.
49
+ const output = stdout.toString().trimEnd();
28
50
  const errOutput = stderr.toString().trim();
29
51
  if (error) {
30
52
  resolve({
@@ -36,7 +58,7 @@ async function execGitArgs(args, cwd, timeout = 30000) {
36
58
  else {
37
59
  resolve({
38
60
  success: true,
39
- output: output || '(no output)',
61
+ output,
40
62
  error: errOutput || undefined,
41
63
  });
42
64
  }
@@ -49,13 +71,13 @@ async function execGitArgs(args, cwd, timeout = 30000) {
49
71
  async function checkUncommittedChanges(cwd) {
50
72
  const statusResult = await execGit('status --porcelain', cwd);
51
73
  if (!statusResult.success) {
52
- return { hasChanges: false, files: [] };
74
+ return { success: false, error: statusResult.error || 'unknown git status error' };
53
75
  }
54
76
  const files = statusResult.output
55
77
  .split('\n')
56
78
  .filter(line => line.trim())
57
79
  .map(line => line.slice(3).trim()); // 去除状态码
58
- return { hasChanges: files.length > 0, files };
80
+ return { success: true, hasChanges: files.length > 0, files };
59
81
  }
60
82
  /**
61
83
  * 检查远程认证状态
@@ -99,7 +121,7 @@ exports.gitStatusTool = (0, tool_1.buildTool)({
99
121
  // git status --porcelain
100
122
  const statusResult = await execGit('status --porcelain', cwd);
101
123
  if (!statusResult.success) {
102
- return { success: false, output: '', error: `git status failed: ${statusResult.error}` };
124
+ return { success: false, output: `git status failed: ${statusResult.error}`, error: `git status failed: ${statusResult.error}` };
103
125
  }
104
126
  // 解析状态
105
127
  const lines = statusResult.output.split('\n').filter(l => l.trim());
@@ -121,12 +143,36 @@ exports.gitStatusTool = (0, tool_1.buildTool)({
121
143
  }
122
144
  }
123
145
  }
146
+ // Upstream divergence is best-effort: a detached HEAD or a branch without an
147
+ // upstream makes `rev-list` fail, and that must never turn a successful
148
+ // `git status` into an error.
149
+ let ahead = 0;
150
+ let behind = 0;
151
+ try {
152
+ const upstream = await execGitArgs(['rev-list', '--count', '--left-right', '@{upstream}...HEAD'], cwd);
153
+ if (upstream.success && upstream.output.includes('\t')) {
154
+ // `--left-right` prints "<left>\t<right>" for `@{upstream}...HEAD`:
155
+ // left = commits in upstream but not HEAD -> we are behind
156
+ // right = commits in HEAD but not upstream -> we are ahead
157
+ const [behindCount, aheadCount] = upstream.output
158
+ .trim()
159
+ .split('\t')
160
+ .map(value => parseInt(value, 10) || 0);
161
+ behind = behindCount;
162
+ ahead = aheadCount;
163
+ }
164
+ }
165
+ catch {
166
+ // no upstream / detached HEAD -> leave ahead=behind=0
167
+ }
124
168
  const summary = {
125
169
  clean: lines.length === 0,
126
170
  untracked,
127
171
  modified,
128
172
  staged,
129
173
  total: lines.length,
174
+ ahead,
175
+ behind,
130
176
  };
131
177
  const output = JSON.stringify(summary, null, 2);
132
178
  return {
@@ -144,15 +190,16 @@ exports.gitStatusTool = (0, tool_1.buildTool)({
144
190
  // ============================================================================
145
191
  exports.gitPushTool = (0, tool_1.buildTool)({
146
192
  name: 'git_push',
147
- description: `安全执行 git push,自动验证 git status 和认证状态。
193
+ description: `安全执行 git push,自动验证 git status、显式 staging 边界和认证状态。
148
194
 
149
195
  工作流程:
150
196
  1. 检查 git status --porcelain(未暂存/未提交的文件)
151
- 2. 可选自动 git add -A 添加所有变更
197
+ 2. 仅对显式文件 paths 执行 git add -- <paths>;拒绝目录、glob/pathspec 和预暂存越界文件
152
198
  3. git commit(如果需要)
153
- 4. 检查远程认证状态
154
- 5. git push
155
- 6. 验证 push 成功
199
+ 4. 若提交后仍有未提交文件,在任何远程写入前停止
200
+ 5. 检查远程认证状态
201
+ 6. git push
202
+ 7. 验证 push 成功
156
203
 
157
204
  Issue #18/#23 修复:不再在未验证的情况下声称成功。`,
158
205
  parameters: {
@@ -164,7 +211,12 @@ Issue #18/#23 修复:不再在未验证的情况下声称成功。`,
164
211
  },
165
212
  add_all: {
166
213
  type: 'boolean',
167
- description: '是否自动 git add -A(默认 true)',
214
+ description: '已废弃且禁止;请使用 paths 显式列出要暂存的文件',
215
+ },
216
+ paths: {
217
+ type: 'array',
218
+ items: { type: 'string' },
219
+ description: '要暂存的精确仓库相对文件路径;存在工作区变更时必填',
168
220
  },
169
221
  cwd: {
170
222
  type: 'string',
@@ -179,29 +231,164 @@ Issue #18/#23 修复:不再在未验证的情况下声称成功。`,
179
231
  },
180
232
  execute: async (args) => {
181
233
  const message = args.message;
182
- const addAll = args.add_all ?? true;
234
+ const addAll = args.add_all ?? false;
235
+ const rawPaths = args.paths;
183
236
  const cwd = args.cwd;
184
237
  const verify = args.verify ?? true;
185
238
  if (!message || typeof message !== 'string') {
186
239
  return { success: false, output: '', error: 'git_push requires a commit message' };
187
240
  }
241
+ if (addAll) {
242
+ return {
243
+ success: false,
244
+ output: '',
245
+ error: 'git_push add_all=true is disabled; provide an explicit paths allowlist',
246
+ };
247
+ }
248
+ if (rawPaths !== undefined && !Array.isArray(rawPaths)) {
249
+ return { success: false, output: '', error: 'git_push paths must be an array of strings' };
250
+ }
251
+ const paths = rawPaths ?? [];
252
+ if (paths.some(path => typeof path !== 'string')) {
253
+ return {
254
+ success: false,
255
+ output: '',
256
+ error: 'git_push paths must contain only strings',
257
+ };
258
+ }
259
+ const normalizedPaths = paths.map(normalizeStagePath);
260
+ if (normalizedPaths.some(path => path === null)) {
261
+ return {
262
+ success: false,
263
+ output: '',
264
+ error: 'git_push paths must be exact repository-relative files without glob or pathspec syntax',
265
+ };
266
+ }
267
+ const stagePaths = [...new Set(normalizedPaths)];
188
268
  const log = [];
189
269
  // 1. 检查当前状态
190
270
  log.push('🔍 Checking git status...');
191
271
  const changes = await checkUncommittedChanges(cwd);
272
+ if (!changes.success) {
273
+ return {
274
+ success: false,
275
+ output: log.join('\n'),
276
+ error: `git status failed: ${changes.error}`,
277
+ };
278
+ }
192
279
  if (changes.hasChanges) {
193
280
  log.push(` Found ${changes.files.length} uncommitted files: ${changes.files.slice(0, 5).join(', ')}${changes.files.length > 5 ? '...' : ''}`);
194
- // 2. git add(如果启用)
195
- if (addAll) {
196
- log.push('📦 Running git add -A...');
197
- const addResult = await execGit('add -A', cwd);
198
- if (!addResult.success) {
199
- return { success: false, output: log.join('\n'), error: `git add failed: ${addResult.error}` };
281
+ // 2. 只暂存显式文件 allowlist;永不继承或扩大现有 staging 边界。
282
+ if (stagePaths.length === 0) {
283
+ return {
284
+ success: false,
285
+ output: log.join('\n'),
286
+ error: 'Uncommitted changes require an explicit file paths allowlist',
287
+ };
288
+ }
289
+ const expectedStagePaths = new Set(stagePaths);
290
+ for (const path of stagePaths) {
291
+ const exactPathResult = await execGitArgs(['ls-files', '--cached', '--others', '--exclude-standard', '-z', '--', path], cwd);
292
+ if (!exactPathResult.success) {
293
+ return {
294
+ success: false,
295
+ output: log.join('\n'),
296
+ error: `Exact staging-path verification failed for ${path}: ${exactPathResult.error}`,
297
+ };
298
+ }
299
+ const matchingPaths = parseStagedPaths(exactPathResult.output);
300
+ if (matchingPaths.length !== 1 || matchingPaths[0] !== path) {
301
+ return {
302
+ success: false,
303
+ output: log.join('\n'),
304
+ error: `git_push paths must identify exact files, not directories or expanded pathspecs: ${path}`,
305
+ };
200
306
  }
201
- log.push(' ✓ Files added to staging');
202
307
  }
203
- else {
204
- log.push(' ⚠ add_all=false, skipping git add');
308
+ const initialStagedResult = await execGitArgs(['diff', '--cached', '--name-only', '-z'], cwd);
309
+ if (!initialStagedResult.success) {
310
+ return {
311
+ success: false,
312
+ output: log.join('\n'),
313
+ error: `Initial staged-file verification failed: ${initialStagedResult.error}`,
314
+ };
315
+ }
316
+ const unexpectedInitialPaths = parseStagedPaths(initialStagedResult.output).filter(path => !expectedStagePaths.has(path));
317
+ if (unexpectedInitialPaths.length > 0) {
318
+ return {
319
+ success: false,
320
+ output: log.join('\n'),
321
+ error: `Pre-staged files fall outside the explicit allowlist: ${unexpectedInitialPaths.join(', ')}`,
322
+ };
323
+ }
324
+ const indexSnapshotResult = await execGitArgs(['write-tree'], cwd);
325
+ if (!indexSnapshotResult.success || !/^[0-9a-f]{40,64}$/.test(indexSnapshotResult.output)) {
326
+ return {
327
+ success: false,
328
+ output: log.join('\n'),
329
+ error: `Unable to snapshot the Git index before staging: ${indexSnapshotResult.error || 'invalid tree id'}`,
330
+ };
331
+ }
332
+ const restoreIndex = async () => {
333
+ const result = await execGitArgs(['read-tree', indexSnapshotResult.output], cwd);
334
+ return result.success ? undefined : result.error || 'unknown index restore error';
335
+ };
336
+ log.push(`📦 Staging ${stagePaths.length} explicit file(s)...`);
337
+ const addResult = await execGitArgs(['add', '--', ...stagePaths], cwd);
338
+ if (!addResult.success) {
339
+ const restoreError = await restoreIndex();
340
+ return {
341
+ success: false,
342
+ output: log.join('\n'),
343
+ error: restoreError
344
+ ? `git add failed: ${addResult.error}; index rollback failed: ${restoreError}`
345
+ : `git add failed: ${addResult.error}; index restored`,
346
+ };
347
+ }
348
+ log.push(` ✓ Staged: ${stagePaths.slice(0, 5).join(', ')}${stagePaths.length > 5 ? '...' : ''}`);
349
+ const stagedResult = await execGitArgs(['diff', '--cached', '--name-only', '-z'], cwd);
350
+ if (!stagedResult.success) {
351
+ const restoreError = await restoreIndex();
352
+ return {
353
+ success: false,
354
+ output: log.join('\n'),
355
+ error: restoreError
356
+ ? `Staged-file verification failed: ${stagedResult.error}; index rollback failed: ${restoreError}`
357
+ : `Staged-file verification failed: ${stagedResult.error}; index restored`,
358
+ };
359
+ }
360
+ const stagedFiles = parseStagedPaths(stagedResult.output);
361
+ const unexpectedStagedPaths = stagedFiles.filter(path => !expectedStagePaths.has(path));
362
+ const missingStagedPaths = stagePaths.filter(path => !stagedFiles.includes(path));
363
+ if (unexpectedStagedPaths.length > 0 || missingStagedPaths.length > 0) {
364
+ const restoreError = await restoreIndex();
365
+ return {
366
+ success: false,
367
+ output: log.join('\n'),
368
+ error: [
369
+ 'Staged files do not exactly match the explicit allowlist',
370
+ unexpectedStagedPaths.length > 0
371
+ ? `unexpected: ${unexpectedStagedPaths.join(', ')}`
372
+ : '',
373
+ missingStagedPaths.length > 0 ? `missing: ${missingStagedPaths.join(', ')}` : '',
374
+ restoreError ? `index rollback failed: ${restoreError}` : 'index restored',
375
+ ]
376
+ .filter(Boolean)
377
+ .join('; '),
378
+ };
379
+ }
380
+ log.push(` ✓ Verified ${stagedFiles.length} staged file(s)`);
381
+ const preCommitHead = await execGitArgs(['rev-parse', 'HEAD'], cwd);
382
+ if (!preCommitHead.success || !/^[0-9a-f]{40,64}$/.test(preCommitHead.output)) {
383
+ const restoreError = await restoreIndex();
384
+ return {
385
+ success: false,
386
+ output: log.join('\n'),
387
+ error: [
388
+ `Unable to snapshot HEAD before commit: ${preCommitHead.error || 'invalid commit id'}`,
389
+ restoreError ? `index rollback failed: ${restoreError}` : 'index restored',
390
+ ].join('; '),
391
+ };
205
392
  }
206
393
  // 3. git commit
207
394
  log.push(`📝 Committing with message: "${message.slice(0, 50)}..."`);
@@ -212,12 +399,46 @@ Issue #18/#23 修复:不再在未验证的情况下声称成功。`,
212
399
  log.push(' ⚠ Nothing new to commit');
213
400
  }
214
401
  else {
215
- return { success: false, output: log.join('\n'), error: `git commit failed: ${commitResult.error}` };
402
+ const postFailureHead = await execGitArgs(['rev-parse', 'HEAD'], cwd);
403
+ const restoreError = await restoreIndex();
404
+ const headChanged = postFailureHead.success && postFailureHead.output !== preCommitHead.output;
405
+ const headStatus = !postFailureHead.success
406
+ ? `HEAD verification failed: ${postFailureHead.error || 'unknown error'}`
407
+ : headChanged
408
+ ? `HEAD changed unexpectedly from ${preCommitHead.output} to ${postFailureHead.output}; manual recovery required`
409
+ : undefined;
410
+ return {
411
+ success: false,
412
+ output: log.join('\n'),
413
+ error: [
414
+ `git commit failed: ${commitResult.error}`,
415
+ restoreError ? `index rollback failed: ${restoreError}` : 'index restored',
416
+ headStatus,
417
+ ]
418
+ .filter(Boolean)
419
+ .join('; '),
420
+ };
216
421
  }
217
422
  }
218
423
  else {
219
424
  log.push(' ✓ Commit successful');
220
425
  }
426
+ const postCommitChanges = await checkUncommittedChanges(cwd);
427
+ if (!postCommitChanges.success) {
428
+ return {
429
+ success: false,
430
+ output: log.join('\n'),
431
+ error: `Post-commit git status failed: ${postCommitChanges.error}`,
432
+ };
433
+ }
434
+ if (postCommitChanges.hasChanges) {
435
+ log.push(` ⚠ ${postCommitChanges.files.length} file(s) remain outside the committed boundary`);
436
+ return {
437
+ success: false,
438
+ output: log.join('\n'),
439
+ error: 'Commit created but push was not attempted because the working tree is not clean',
440
+ };
441
+ }
221
442
  }
222
443
  else {
223
444
  log.push(' ✓ Working directory clean, no changes to commit');
@@ -230,7 +451,7 @@ Issue #18/#23 修复:不再在未验证的情况下声称成功。`,
230
451
  return {
231
452
  success: false,
232
453
  output: log.join('\n'),
233
- error: auth.error || 'Remote authentication failed - please configure git credentials'
454
+ error: auth.error || 'Remote authentication failed - please configure git credentials',
234
455
  };
235
456
  }
236
457
  log.push(' ✓ Authentication verified');
@@ -239,14 +460,39 @@ Issue #18/#23 修复:不再在未验证的情况下声称成功。`,
239
460
  log.push('🚀 Pushing to remote...');
240
461
  const pushResult = await execGit('push', cwd, 60000); // 60s timeout
241
462
  if (!pushResult.success) {
242
- return { success: false, output: log.join('\n'), error: `git push failed: ${pushResult.error}` };
463
+ return {
464
+ success: false,
465
+ output: log.join('\n'),
466
+ error: `git push failed: ${pushResult.error}`,
467
+ };
243
468
  }
244
469
  log.push(' ✓ Push completed');
245
470
  // 6. 验证最终状态(v0.1.11 增强)
246
471
  log.push('✅ Verifying final status...');
247
472
  const finalChanges = await checkUncommittedChanges(cwd);
473
+ if (!finalChanges.success) {
474
+ return {
475
+ success: false,
476
+ output: log.join('\n'),
477
+ error: `Final git status failed: ${finalChanges.error}`,
478
+ };
479
+ }
248
480
  const logResult = await execGit('log --oneline -1', cwd);
481
+ if (!logResult.success) {
482
+ return {
483
+ success: false,
484
+ output: log.join('\n'),
485
+ error: `Final git log failed: ${logResult.error}`,
486
+ };
487
+ }
249
488
  const untrackedResult = await execGit('status --short', cwd);
489
+ if (!untrackedResult.success) {
490
+ return {
491
+ success: false,
492
+ output: log.join('\n'),
493
+ error: `Final git status --short failed: ${untrackedResult.error}`,
494
+ };
495
+ }
250
496
  // v0.1.11: 检查是否有未追踪文件(?? 状态)
251
497
  const untrackedFiles = untrackedResult.output
252
498
  .split('\n')
@@ -266,8 +512,29 @@ Issue #18/#23 修复:不再在未验证的情况下声称成功。`,
266
512
  error: 'Push completed but some files remain uncommitted - check git status',
267
513
  };
268
514
  }
515
+ const branchResult = await execGitArgs(['branch', '--show-current'], cwd);
516
+ if (!branchResult.success || !branchResult.output.trim()) {
517
+ return {
518
+ success: false,
519
+ output: log.join('\n'),
520
+ error: `Push completed but current branch verification failed: ${branchResult.error || 'empty branch'}`,
521
+ };
522
+ }
523
+ const branch = branchResult.output.trim();
524
+ const remoteResult = await execGitArgs(['config', '--get', `branch.${branch}.remote`], cwd);
525
+ if (!remoteResult.success || !remoteResult.output.trim()) {
526
+ return {
527
+ success: false,
528
+ output: log.join('\n'),
529
+ error: `Push completed but upstream remote verification failed: ${remoteResult.error || 'missing branch remote'}`,
530
+ };
531
+ }
532
+ const remote = remoteResult.output.trim();
533
+ const latestCommit = logResult.output.split('\n')[0];
269
534
  log.push(` ✓ Working directory clean`);
270
- log.push(` ✓ Latest commit: ${logResult.output.split('\n')[0]}`);
535
+ log.push(` ✓ Pushed branch: ${branch}`);
536
+ log.push(` ✓ Remote: ${remote}`);
537
+ log.push(` ✓ Latest commit: ${latestCommit}`);
271
538
  return {
272
539
  success: true,
273
540
  output: log.join('\n'),
@@ -275,11 +542,299 @@ Issue #18/#23 修复:不再在未验证的情况下声称成功。`,
275
542
  },
276
543
  isDestructive: () => true,
277
544
  isConcurrencySafe: () => false,
278
- checkPermissions: () => ({ behavior: 'ask', reason: 'git push modifies remote repository' }),
279
- userFacingName: (args) => `Git Push: ${args.message?.slice(0, 30)}`,
545
+ checkPermissions: args => ({
546
+ behavior: 'ask',
547
+ reason: Array.isArray(args.paths) && args.paths.length > 0
548
+ ? `git push will stage ${args.paths.length} explicit path(s), commit, and modify the remote repository`
549
+ : 'git push will modify the remote repository and refuses uncommitted changes without explicit paths',
550
+ }),
551
+ userFacingName: args => `Git Push: ${args.message?.slice(0, 30)}`,
552
+ });
553
+ // ============================================================================
554
+ // git_commit 工具
555
+ // ============================================================================
556
+ exports.gitCommitTool = (0, tool_1.buildTool)({
557
+ name: 'git_commit',
558
+ description: `提交工作区变更到本地仓库。
559
+
560
+ 工作流程:
561
+ 1. 检查 git status --porcelain
562
+ 2. 仅对显式 paths 暂存(或 all=true 暂存全部已追踪变更)
563
+ 3. git commit -m <message>
564
+ 4. 验证 commit 成功
565
+
566
+ 安全:要求明确 message;拒绝盲目暂存未受控文件。`,
567
+ parameters: {
568
+ type: 'object',
569
+ properties: {
570
+ message: { type: 'string', description: 'Commit message(必填)' },
571
+ paths: {
572
+ type: 'array',
573
+ items: { type: 'string' },
574
+ description: '要暂存的精确仓库相对文件路径;与 all 互斥',
575
+ },
576
+ all: {
577
+ type: 'boolean',
578
+ description: '暂存所有已追踪文件的变更(不含未追踪文件)',
579
+ },
580
+ cwd: { type: 'string', description: '工作目录(可选)' },
581
+ },
582
+ required: ['message'],
583
+ },
584
+ execute: async (args) => {
585
+ const message = args.message;
586
+ const rawPaths = args.paths;
587
+ const all = args.all ?? false;
588
+ const cwd = args.cwd;
589
+ if (!message || typeof message !== 'string') {
590
+ return {
591
+ success: false,
592
+ output: 'git_commit requires a commit message',
593
+ error: 'git_commit requires a commit message',
594
+ };
595
+ }
596
+ if (rawPaths !== undefined && !Array.isArray(rawPaths)) {
597
+ return {
598
+ success: false,
599
+ output: 'git_commit paths must be an array of strings',
600
+ error: 'git_commit paths must be an array of strings',
601
+ };
602
+ }
603
+ const paths = rawPaths ?? [];
604
+ if (paths.some(item => typeof item !== 'string')) {
605
+ return {
606
+ success: false,
607
+ output: 'git_commit paths must contain only strings',
608
+ error: 'git_commit paths must contain only strings',
609
+ };
610
+ }
611
+ const normalized = paths.map(normalizeStagePath);
612
+ if (normalized.some(item => item === null)) {
613
+ return {
614
+ success: false,
615
+ output: 'git_commit paths must be exact repository-relative files without glob or pathspec syntax',
616
+ error: 'git_commit paths must be exact repository-relative files without glob or pathspec syntax',
617
+ };
618
+ }
619
+ const stagePaths = [...new Set(normalized)];
620
+ const log = [];
621
+ log.push('🔍 Checking git status...');
622
+ const changes = await checkUncommittedChanges(cwd);
623
+ if (!changes.success) {
624
+ return { success: false, output: log.join('\n'), error: `git status failed: ${changes.error}` };
625
+ }
626
+ if (!changes.hasChanges && stagePaths.length === 0 && !all) {
627
+ return { success: true, output: '✓ Working directory clean, nothing to commit' };
628
+ }
629
+ if (all) {
630
+ log.push('📦 Staging all tracked changes...');
631
+ const addResult = await execGit('add -u', cwd);
632
+ if (!addResult.success) {
633
+ return { success: false, output: log.join('\n'), error: `git add -u failed: ${addResult.error}` };
634
+ }
635
+ }
636
+ else if (stagePaths.length > 0) {
637
+ log.push(`📦 Staging ${stagePaths.length} explicit path(s)...`);
638
+ const addResult = await execGitArgs(['add', '--', ...stagePaths], cwd);
639
+ if (!addResult.success) {
640
+ return { success: false, output: log.join('\n'), error: `git add failed: ${addResult.error}` };
641
+ }
642
+ }
643
+ else {
644
+ return {
645
+ success: false,
646
+ output: log.join('\n'),
647
+ error: 'No changes staged: provide paths or set all=true',
648
+ };
649
+ }
650
+ log.push(`📝 Committing: "${message.slice(0, 50)}..."`);
651
+ const commitResult = await execGitArgs(['commit', '-m', message], cwd);
652
+ if (!commitResult.success) {
653
+ await execGit('reset', cwd);
654
+ if (commitResult.output.includes('nothing to commit')) {
655
+ return { success: true, output: log.join('\n') + '\n ⚠ Nothing new to commit' };
656
+ }
657
+ return { success: false, output: log.join('\n'), error: `git commit failed: ${commitResult.error}` };
658
+ }
659
+ log.push(' ✓ Commit successful');
660
+ const logResult = await execGit('log --oneline -1', cwd);
661
+ if (logResult.success)
662
+ log.push(` ✓ Latest commit: ${logResult.output.split('\n')[0]}`);
663
+ return { success: true, output: log.join('\n') };
664
+ },
665
+ isDestructive: () => false,
666
+ isConcurrencySafe: () => false,
667
+ checkPermissions: () => ({
668
+ behavior: 'ask',
669
+ reason: 'git commit will create a new commit in the local repository',
670
+ }),
671
+ userFacingName: args => `Git Commit: ${args.message?.slice(0, 30)}`,
672
+ });
673
+ // ============================================================================
674
+ // git_diff 工具
675
+ // ============================================================================
676
+ exports.gitDiffTool = (0, tool_1.buildTool)({
677
+ name: 'git_diff',
678
+ description: '显示 Git 差异。默认工作区 vs 暂存区;staged=true 显示已暂存 vs HEAD;可指定 paths。',
679
+ parameters: {
680
+ type: 'object',
681
+ properties: {
682
+ staged: { type: 'boolean', description: '显示已暂存变更(vs HEAD),默认 false' },
683
+ stat: { type: 'boolean', description: '仅显示统计摘要(默认 false)' },
684
+ paths: { type: 'array', items: { type: 'string' }, description: '限定路径(可选)' },
685
+ cwd: { type: 'string', description: '工作目录(可选)' },
686
+ },
687
+ required: [],
688
+ },
689
+ execute: async (args) => {
690
+ const staged = args.staged ?? false;
691
+ const stat = args.stat ?? false;
692
+ const rawPaths = args.paths;
693
+ const cwd = args.cwd;
694
+ const paths = Array.isArray(rawPaths) ? rawPaths.map(String) : [];
695
+ const cmd = ['diff', '--no-color'];
696
+ if (stat)
697
+ cmd.push('--stat');
698
+ if (staged)
699
+ cmd.push('--cached');
700
+ if (paths.length)
701
+ cmd.push('--', ...paths);
702
+ const result = await execGitArgs(cmd, cwd, 60000);
703
+ if (!result.success) {
704
+ return { success: false, output: `git diff failed: ${result.error}`, error: `git diff failed: ${result.error}` };
705
+ }
706
+ const MAX = 20000;
707
+ const out = result.output.length > MAX
708
+ ? `${result.output.slice(0, MAX)}\n… (truncated, ${result.output.length} chars total)`
709
+ : result.output;
710
+ return { success: true, output: out || 'No differences' };
711
+ },
712
+ isReadOnly: () => true,
713
+ isConcurrencySafe: () => true,
714
+ checkPermissions: () => ({ behavior: 'allow' }),
715
+ userFacingName: () => 'Git Diff',
716
+ });
717
+ // ============================================================================
718
+ // git_log 工具
719
+ // ============================================================================
720
+ exports.gitLogTool = (0, tool_1.buildTool)({
721
+ name: 'git_log',
722
+ description: '显示提交历史。可指定条数与格式。',
723
+ parameters: {
724
+ type: 'object',
725
+ properties: {
726
+ max_count: { type: 'number', description: '返回的最大提交数(默认 20,上限 200)' },
727
+ oneline: { type: 'boolean', description: '单行精简格式(默认 true)' },
728
+ cwd: { type: 'string', description: '工作目录(可选)' },
729
+ },
730
+ required: [],
731
+ },
732
+ execute: async (args) => {
733
+ const maxCount = typeof args.max_count === 'number' ? Math.min(Math.max(args.max_count, 1), 200) : 20;
734
+ const oneline = args.oneline ?? true;
735
+ const cwd = args.cwd;
736
+ const fmt = oneline ? '%h %s (%an, %ar)' : '%H%nAuthor: %an <%ae>%nDate: %ad%n%n%B';
737
+ const cmd = ['log', `--max-count=${maxCount}`, `--pretty=format:${fmt}`, '--no-color'];
738
+ if (!oneline)
739
+ cmd.push('--date=iso');
740
+ const result = await execGitArgs(cmd, cwd, 30000);
741
+ if (!result.success) {
742
+ return { success: false, output: `git log failed: ${result.error}`, error: `git log failed: ${result.error}` };
743
+ }
744
+ return { success: true, output: result.output || 'No commits' };
745
+ },
746
+ isReadOnly: () => true,
747
+ isConcurrencySafe: () => true,
748
+ checkPermissions: () => ({ behavior: 'allow' }),
749
+ userFacingName: () => 'Git Log',
750
+ });
751
+ // ============================================================================
752
+ // git_branch 工具
753
+ // ============================================================================
754
+ exports.gitBranchTool = (0, tool_1.buildTool)({
755
+ name: 'git_branch',
756
+ description: `分支操作。
757
+
758
+ action:
759
+ - list(默认): 列出本地分支,标记当前分支(*)与上游跟踪
760
+ - create: 基于当前 HEAD 创建新分支(不切换)
761
+ - switch: 切换到已有分支
762
+ - delete: 删除本地分支(需 force 才允许未合并删除)`,
763
+ parameters: {
764
+ type: 'object',
765
+ properties: {
766
+ action: {
767
+ type: 'string',
768
+ enum: ['list', 'create', 'switch', 'delete'],
769
+ description: '操作类型(默认 list)',
770
+ },
771
+ name: { type: 'string', description: '分支名(create/switch/delete 必填)' },
772
+ force: { type: 'boolean', description: 'delete 时允许删除未合并分支(默认 false)' },
773
+ cwd: { type: 'string', description: '工作目录(可选)' },
774
+ },
775
+ required: [],
776
+ },
777
+ execute: async (args) => {
778
+ const action = args.action ?? 'list';
779
+ const name = args.name;
780
+ const force = args.force ?? false;
781
+ const cwd = args.cwd;
782
+ const log = [];
783
+ if (action === 'list') {
784
+ const result = await execGit('branch -vv', cwd);
785
+ if (!result.success) {
786
+ return { success: false, output: `git branch -vv failed: ${result.error}`, error: `git branch -vv failed: ${result.error}` };
787
+ }
788
+ return { success: true, output: result.output || 'No branches' };
789
+ }
790
+ if (!name || typeof name !== 'string') {
791
+ return { success: false, output: '', error: `git_branch ${action} requires a branch name` };
792
+ }
793
+ if (action === 'create') {
794
+ const result = await execGitArgs(['branch', name], cwd);
795
+ if (!result.success) {
796
+ return { success: false, output: log.join('\n'), error: `git branch create failed: ${result.error}` };
797
+ }
798
+ log.push(`✓ Created branch ${name}`);
799
+ return { success: true, output: log.join('\n') };
800
+ }
801
+ if (action === 'switch') {
802
+ const result = await execGitArgs(['checkout', name], cwd);
803
+ if (!result.success) {
804
+ return { success: false, output: log.join('\n'), error: `git checkout failed: ${result.error}` };
805
+ }
806
+ log.push(`✓ Switched to ${name}`);
807
+ return { success: true, output: log.join('\n') };
808
+ }
809
+ if (action === 'delete') {
810
+ const result = await execGitArgs(force ? ['branch', '-D', name] : ['branch', '-d', name], cwd);
811
+ if (!result.success) {
812
+ return { success: false, output: log.join('\n'), error: `git branch delete failed: ${result.error}` };
813
+ }
814
+ log.push(`✓ Deleted branch ${name}`);
815
+ return { success: true, output: log.join('\n') };
816
+ }
817
+ return { success: false, output: `Unknown git_branch action: ${action}`, error: `Unknown git_branch action: ${action}` };
818
+ },
819
+ isDestructive: () => false,
820
+ isConcurrencySafe: () => false,
821
+ checkPermissions: args => {
822
+ const action = args.action ?? 'list';
823
+ if (action === 'list')
824
+ return { behavior: 'allow' };
825
+ return { behavior: 'ask', reason: `git branch ${action} will modify local branch state` };
826
+ },
827
+ userFacingName: args => `Git Branch: ${args.action ?? 'list'}`,
280
828
  });
281
829
  // ============================================================================
282
830
  // 导出
283
831
  // ============================================================================
284
- exports.GIT_TOOLS = [exports.gitStatusTool, exports.gitPushTool];
832
+ exports.GIT_TOOLS = [
833
+ exports.gitStatusTool,
834
+ exports.gitPushTool,
835
+ exports.gitCommitTool,
836
+ exports.gitDiffTool,
837
+ exports.gitLogTool,
838
+ exports.gitBranchTool,
839
+ ];
285
840
  //# sourceMappingURL=git.js.map