openhorse 0.1.5
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.
- package/README.md +460 -0
- package/bin/openhorse +56 -0
- package/dist/agents/coder.d.ts +12 -0
- package/dist/agents/coder.d.ts.map +1 -0
- package/dist/agents/coder.js +48 -0
- package/dist/agents/coder.js.map +1 -0
- package/dist/agents/leader.d.ts +12 -0
- package/dist/agents/leader.d.ts.map +1 -0
- package/dist/agents/leader.js +49 -0
- package/dist/agents/leader.js.map +1 -0
- package/dist/agents/router.d.ts +59 -0
- package/dist/agents/router.d.ts.map +1 -0
- package/dist/agents/router.js +193 -0
- package/dist/agents/router.js.map +1 -0
- package/dist/cli-ink.d.ts +7 -0
- package/dist/cli-ink.d.ts.map +1 -0
- package/dist/cli-ink.js +135 -0
- package/dist/cli-ink.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +638 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/index.d.ts +12 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +1095 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/parser.d.ts +26 -0
- package/dist/commands/parser.d.ts.map +1 -0
- package/dist/commands/parser.js +61 -0
- package/dist/commands/parser.js.map +1 -0
- package/dist/commands/types.d.ts +61 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +32 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/core/agent.d.ts +66 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +55 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/brain.d.ts +41 -0
- package/dist/core/brain.d.ts.map +1 -0
- package/dist/core/brain.js +92 -0
- package/dist/core/brain.js.map +1 -0
- package/dist/core/cost-tracker.d.ts +107 -0
- package/dist/core/cost-tracker.d.ts.map +1 -0
- package/dist/core/cost-tracker.js +199 -0
- package/dist/core/cost-tracker.js.map +1 -0
- package/dist/core/strategy-tracker.d.ts +61 -0
- package/dist/core/strategy-tracker.d.ts.map +1 -0
- package/dist/core/strategy-tracker.js +124 -0
- package/dist/core/strategy-tracker.js.map +1 -0
- package/dist/framework/index.d.ts +20 -0
- package/dist/framework/index.d.ts.map +1 -0
- package/dist/framework/index.js +29 -0
- package/dist/framework/index.js.map +1 -0
- package/dist/framework/prompt.d.ts +40 -0
- package/dist/framework/prompt.d.ts.map +1 -0
- package/dist/framework/prompt.js +112 -0
- package/dist/framework/prompt.js.map +1 -0
- package/dist/framework/query.d.ts +86 -0
- package/dist/framework/query.d.ts.map +1 -0
- package/dist/framework/query.js +177 -0
- package/dist/framework/query.js.map +1 -0
- package/dist/framework/store.d.ts +64 -0
- package/dist/framework/store.d.ts.map +1 -0
- package/dist/framework/store.js +78 -0
- package/dist/framework/store.js.map +1 -0
- package/dist/framework/tool-state.d.ts +22 -0
- package/dist/framework/tool-state.d.ts.map +1 -0
- package/dist/framework/tool-state.js +40 -0
- package/dist/framework/tool-state.js.map +1 -0
- package/dist/framework/tool.d.ts +88 -0
- package/dist/framework/tool.d.ts.map +1 -0
- package/dist/framework/tool.js +60 -0
- package/dist/framework/tool.js.map +1 -0
- package/dist/harness/harness.d.ts +96 -0
- package/dist/harness/harness.d.ts.map +1 -0
- package/dist/harness/harness.js +224 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/harness/safety.d.ts +89 -0
- package/dist/harness/safety.d.ts.map +1 -0
- package/dist/harness/safety.js +178 -0
- package/dist/harness/safety.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +178 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +473 -0
- package/dist/init.js.map +1 -0
- package/dist/ink/bidi.d.ts +16 -0
- package/dist/ink/bidi.d.ts.map +1 -0
- package/dist/ink/bidi.js +124 -0
- package/dist/ink/bidi.js.map +1 -0
- package/dist/ink/clearTerminal.d.ts +14 -0
- package/dist/ink/clearTerminal.d.ts.map +1 -0
- package/dist/ink/clearTerminal.js +63 -0
- package/dist/ink/clearTerminal.js.map +1 -0
- package/dist/ink/colorize.d.ts +17 -0
- package/dist/ink/colorize.d.ts.map +1 -0
- package/dist/ink/colorize.js +208 -0
- package/dist/ink/colorize.js.map +1 -0
- package/dist/ink/components/App.d.ts +73 -0
- package/dist/ink/components/App.d.ts.map +1 -0
- package/dist/ink/components/App.js +646 -0
- package/dist/ink/components/App.js.map +1 -0
- package/dist/ink/components/AppContext.d.ts +12 -0
- package/dist/ink/components/AppContext.d.ts.map +1 -0
- package/dist/ink/components/AppContext.js +14 -0
- package/dist/ink/components/AppContext.js.map +1 -0
- package/dist/ink/components/Box.d.ts +44 -0
- package/dist/ink/components/Box.d.ts.map +1 -0
- package/dist/ink/components/Box.js +191 -0
- package/dist/ink/components/Box.js.map +1 -0
- package/dist/ink/components/ClockContext.d.ts +9 -0
- package/dist/ink/components/ClockContext.d.ts.map +1 -0
- package/dist/ink/components/ClockContext.js +146 -0
- package/dist/ink/components/ClockContext.js.map +1 -0
- package/dist/ink/components/CursorDeclarationContext.d.ts +23 -0
- package/dist/ink/components/CursorDeclarationContext.d.ts.map +1 -0
- package/dist/ink/components/CursorDeclarationContext.js +6 -0
- package/dist/ink/components/CursorDeclarationContext.js.map +1 -0
- package/dist/ink/components/ErrorOverview.d.ts +6 -0
- package/dist/ink/components/ErrorOverview.d.ts.map +1 -0
- package/dist/ink/components/ErrorOverview.js +27 -0
- package/dist/ink/components/ErrorOverview.js.map +1 -0
- package/dist/ink/components/Newline.d.ts +13 -0
- package/dist/ink/components/Newline.d.ts.map +1 -0
- package/dist/ink/components/Newline.js +36 -0
- package/dist/ink/components/Newline.js.map +1 -0
- package/dist/ink/components/NoSelect.d.ts +20 -0
- package/dist/ink/components/NoSelect.d.ts.map +1 -0
- package/dist/ink/components/NoSelect.js +63 -0
- package/dist/ink/components/NoSelect.js.map +1 -0
- package/dist/ink/components/RawAnsi.d.ts +17 -0
- package/dist/ink/components/RawAnsi.d.ts.map +1 -0
- package/dist/ink/components/RawAnsi.js +52 -0
- package/dist/ink/components/RawAnsi.js.map +1 -0
- package/dist/ink/components/Spacer.d.ts +6 -0
- package/dist/ink/components/Spacer.d.ts.map +1 -0
- package/dist/ink/components/Spacer.js +26 -0
- package/dist/ink/components/Spacer.js.map +1 -0
- package/dist/ink/components/StdinContext.d.ts +28 -0
- package/dist/ink/components/StdinContext.d.ts.map +1 -0
- package/dist/ink/components/StdinContext.js +19 -0
- package/dist/ink/components/StdinContext.js.map +1 -0
- package/dist/ink/components/TerminalFocusContext.d.ts +10 -0
- package/dist/ink/components/TerminalFocusContext.d.ts.map +1 -0
- package/dist/ink/components/TerminalFocusContext.js +81 -0
- package/dist/ink/components/TerminalFocusContext.js.map +1 -0
- package/dist/ink/components/TerminalSizeContext.d.ts +6 -0
- package/dist/ink/components/TerminalSizeContext.d.ts.map +1 -0
- package/dist/ink/components/TerminalSizeContext.js +6 -0
- package/dist/ink/components/TerminalSizeContext.js.map +1 -0
- package/dist/ink/components/Text.d.ts +56 -0
- package/dist/ink/components/Text.d.ts.map +1 -0
- package/dist/ink/components/Text.js +201 -0
- package/dist/ink/components/Text.js.map +1 -0
- package/dist/ink/constants.d.ts +2 -0
- package/dist/ink/constants.d.ts.map +1 -0
- package/dist/ink/constants.js +6 -0
- package/dist/ink/constants.js.map +1 -0
- package/dist/ink/devtools.d.ts +3 -0
- package/dist/ink/devtools.d.ts.map +1 -0
- package/dist/ink/devtools.js +5 -0
- package/dist/ink/devtools.js.map +1 -0
- package/dist/ink/dom.d.ts +77 -0
- package/dist/ink/dom.d.ts.map +1 -0
- package/dist/ink/dom.js +322 -0
- package/dist/ink/dom.js.map +1 -0
- package/dist/ink/events/click-event.d.ts +32 -0
- package/dist/ink/events/click-event.d.ts.map +1 -0
- package/dist/ink/events/click-event.js +30 -0
- package/dist/ink/events/click-event.js.map +1 -0
- package/dist/ink/events/dispatcher.d.ts +41 -0
- package/dist/ink/events/dispatcher.d.ts.map +1 -0
- package/dist/ink/events/dispatcher.js +181 -0
- package/dist/ink/events/dispatcher.js.map +1 -0
- package/dist/ink/events/emitter.d.ts +6 -0
- package/dist/ink/events/emitter.d.ts.map +1 -0
- package/dist/ink/events/emitter.js +36 -0
- package/dist/ink/events/emitter.js.map +1 -0
- package/dist/ink/events/event-handlers.d.ts +47 -0
- package/dist/ink/events/event-handlers.d.ts.map +1 -0
- package/dist/ink/events/event-handlers.js +34 -0
- package/dist/ink/events/event-handlers.js.map +1 -0
- package/dist/ink/events/event.d.ts +6 -0
- package/dist/ink/events/event.d.ts.map +1 -0
- package/dist/ink/events/event.js +16 -0
- package/dist/ink/events/event.js.map +1 -0
- package/dist/ink/events/focus-event.d.ts +14 -0
- package/dist/ink/events/focus-event.d.ts.map +1 -0
- package/dist/ink/events/focus-event.js +20 -0
- package/dist/ink/events/focus-event.js.map +1 -0
- package/dist/ink/events/input-event.d.ts +31 -0
- package/dist/ink/events/input-event.d.ts.map +1 -0
- package/dist/ink/events/input-event.js +163 -0
- package/dist/ink/events/input-event.js.map +1 -0
- package/dist/ink/events/keyboard-event.d.ts +20 -0
- package/dist/ink/events/keyboard-event.d.ts.map +1 -0
- package/dist/ink/events/keyboard-event.js +44 -0
- package/dist/ink/events/keyboard-event.js.map +1 -0
- package/dist/ink/events/terminal-event.d.ts +55 -0
- package/dist/ink/events/terminal-event.d.ts.map +1 -0
- package/dist/ink/events/terminal-event.js +79 -0
- package/dist/ink/events/terminal-event.js.map +1 -0
- package/dist/ink/events/terminal-focus-event.d.ts +14 -0
- package/dist/ink/events/terminal-focus-event.d.ts.map +1 -0
- package/dist/ink/events/terminal-focus-event.js +19 -0
- package/dist/ink/events/terminal-focus-event.js.map +1 -0
- package/dist/ink/focus.d.ts +44 -0
- package/dist/ink/focus.d.ts.map +1 -0
- package/dist/ink/focus.js +164 -0
- package/dist/ink/focus.js.map +1 -0
- package/dist/ink/frame.d.ts +95 -0
- package/dist/ink/frame.d.ts.map +1 -0
- package/dist/ink/frame.js +35 -0
- package/dist/ink/frame.js.map +1 -0
- package/dist/ink/get-max-width.d.ts +18 -0
- package/dist/ink/get-max-width.d.ts.map +1 -0
- package/dist/ink/get-max-width.js +26 -0
- package/dist/ink/get-max-width.js.map +1 -0
- package/dist/ink/hit-test.d.ts +34 -0
- package/dist/ink/hit-test.d.ts.map +1 -0
- package/dist/ink/hit-test.js +119 -0
- package/dist/ink/hit-test.js.map +1 -0
- package/dist/ink/hooks/use-animation-frame.d.ts +27 -0
- package/dist/ink/hooks/use-animation-frame.d.ts.map +1 -0
- package/dist/ink/hooks/use-animation-frame.js +52 -0
- package/dist/ink/hooks/use-animation-frame.js.map +1 -0
- package/dist/ink/hooks/use-app.d.ts +6 -0
- package/dist/ink/hooks/use-app.d.ts.map +1 -0
- package/dist/ink/hooks/use-app.js +13 -0
- package/dist/ink/hooks/use-app.js.map +1 -0
- package/dist/ink/hooks/use-declared-cursor.d.ts +27 -0
- package/dist/ink/hooks/use-declared-cursor.d.ts.map +1 -0
- package/dist/ink/hooks/use-declared-cursor.js +67 -0
- package/dist/ink/hooks/use-declared-cursor.js.map +1 -0
- package/dist/ink/hooks/use-input.d.ts +38 -0
- package/dist/ink/hooks/use-input.d.ts.map +1 -0
- package/dist/ink/hooks/use-input.js +86 -0
- package/dist/ink/hooks/use-input.js.map +1 -0
- package/dist/ink/hooks/use-interval.d.ts +19 -0
- package/dist/ink/hooks/use-interval.d.ts.map +1 -0
- package/dist/ink/hooks/use-interval.js +59 -0
- package/dist/ink/hooks/use-interval.js.map +1 -0
- package/dist/ink/hooks/use-search-highlight.d.ts +31 -0
- package/dist/ink/hooks/use-search-highlight.d.ts.map +1 -0
- package/dist/ink/hooks/use-search-highlight.js +39 -0
- package/dist/ink/hooks/use-search-highlight.js.map +1 -0
- package/dist/ink/hooks/use-selection.d.ts +40 -0
- package/dist/ink/hooks/use-selection.d.ts.map +1 -0
- package/dist/ink/hooks/use-selection.js +68 -0
- package/dist/ink/hooks/use-selection.js.map +1 -0
- package/dist/ink/hooks/use-stdin.d.ts +6 -0
- package/dist/ink/hooks/use-stdin.d.ts.map +1 -0
- package/dist/ink/hooks/use-stdin.js +13 -0
- package/dist/ink/hooks/use-stdin.js.map +1 -0
- package/dist/ink/hooks/use-tab-status.d.ts +14 -0
- package/dist/ink/hooks/use-tab-status.d.ts.map +1 -0
- package/dist/ink/hooks/use-tab-status.js +61 -0
- package/dist/ink/hooks/use-tab-status.js.map +1 -0
- package/dist/ink/hooks/use-terminal-focus.d.ts +11 -0
- package/dist/ink/hooks/use-terminal-focus.d.ts.map +1 -0
- package/dist/ink/hooks/use-terminal-focus.js +22 -0
- package/dist/ink/hooks/use-terminal-focus.js.map +1 -0
- package/dist/ink/hooks/use-terminal-title.d.ts +13 -0
- package/dist/ink/hooks/use-terminal-title.d.ts.map +1 -0
- package/dist/ink/hooks/use-terminal-title.js +36 -0
- package/dist/ink/hooks/use-terminal-title.js.map +1 -0
- package/dist/ink/hooks/use-terminal-viewport.d.ts +30 -0
- package/dist/ink/hooks/use-terminal-viewport.d.ts.map +1 -0
- package/dist/ink/hooks/use-terminal-viewport.js +81 -0
- package/dist/ink/hooks/use-terminal-viewport.js.map +1 -0
- package/dist/ink/index.d.ts +54 -0
- package/dist/ink/index.d.ts.map +1 -0
- package/dist/ink/index.js +111 -0
- package/dist/ink/index.js.map +1 -0
- package/dist/ink/ink.d.ts +371 -0
- package/dist/ink/ink.d.ts.map +1 -0
- package/dist/ink/ink.js +1686 -0
- package/dist/ink/ink.js.map +1 -0
- package/dist/ink/instances.d.ts +4 -0
- package/dist/ink/instances.d.ts.map +1 -0
- package/dist/ink/instances.js +10 -0
- package/dist/ink/instances.js.map +1 -0
- package/dist/ink/line-width-cache.d.ts +2 -0
- package/dist/ink/line-width-cache.d.ts.map +1 -0
- package/dist/ink/line-width-cache.js +23 -0
- package/dist/ink/line-width-cache.js.map +1 -0
- package/dist/ink/log-update.d.ts +18 -0
- package/dist/ink/log-update.d.ts.map +1 -0
- package/dist/ink/log-update.js +637 -0
- package/dist/ink/log-update.js.map +1 -0
- package/dist/ink/measure-element.d.ts +17 -0
- package/dist/ink/measure-element.d.ts.map +1 -0
- package/dist/ink/measure-element.js +11 -0
- package/dist/ink/measure-element.js.map +1 -0
- package/dist/ink/measure-text.d.ts +7 -0
- package/dist/ink/measure-text.d.ts.map +1 -0
- package/dist/ink/measure-text.js +38 -0
- package/dist/ink/measure-text.js.map +1 -0
- package/dist/ink/node-cache.d.ts +21 -0
- package/dist/ink/node-cache.d.ts.map +1 -0
- package/dist/ink/node-cache.js +36 -0
- package/dist/ink/node-cache.js.map +1 -0
- package/dist/ink/optimizer.d.ts +16 -0
- package/dist/ink/optimizer.d.ts.map +1 -0
- package/dist/ink/optimizer.js +85 -0
- package/dist/ink/optimizer.js.map +1 -0
- package/dist/ink/output.d.ts +120 -0
- package/dist/ink/output.d.ts.map +1 -0
- package/dist/ink/output.js +559 -0
- package/dist/ink/output.js.map +1 -0
- package/dist/ink/parse-keypress.d.ts +112 -0
- package/dist/ink/parse-keypress.d.ts.map +1 -0
- package/dist/ink/parse-keypress.js +719 -0
- package/dist/ink/parse-keypress.js.map +1 -0
- package/dist/ink/parse-keypress.test.d.ts +2 -0
- package/dist/ink/parse-keypress.test.d.ts.map +1 -0
- package/dist/ink/parse-keypress.test.js +37 -0
- package/dist/ink/parse-keypress.test.js.map +1 -0
- package/dist/ink/reconciler.d.ts +12 -0
- package/dist/ink/reconciler.d.ts.map +1 -0
- package/dist/ink/reconciler.js +456 -0
- package/dist/ink/reconciler.js.map +1 -0
- package/dist/ink/render-border.d.ts +25 -0
- package/dist/ink/render-border.d.ts.map +1 -0
- package/dist/ink/render-border.js +141 -0
- package/dist/ink/render-border.js.map +1 -0
- package/dist/ink/render-node-to-output.d.ts +46 -0
- package/dist/ink/render-node-to-output.d.ts.map +1 -0
- package/dist/ink/render-node-to-output.js +1257 -0
- package/dist/ink/render-node-to-output.js.map +1 -0
- package/dist/ink/render-to-screen.d.ts +47 -0
- package/dist/ink/render-to-screen.d.ts.map +1 -0
- package/dist/ink/render-to-screen.js +213 -0
- package/dist/ink/render-to-screen.js.map +1 -0
- package/dist/ink/renderer.d.ts +15 -0
- package/dist/ink/renderer.d.ts.map +1 -0
- package/dist/ink/renderer.js +169 -0
- package/dist/ink/renderer.js.map +1 -0
- package/dist/ink/root.d.ts +75 -0
- package/dist/ink/root.d.ts.map +1 -0
- package/dist/ink/root.js +89 -0
- package/dist/ink/root.js.map +1 -0
- package/dist/ink/screen.d.ts +270 -0
- package/dist/ink/screen.d.ts.map +1 -0
- package/dist/ink/screen.js +1194 -0
- package/dist/ink/screen.js.map +1 -0
- package/dist/ink/searchHighlight.d.ts +21 -0
- package/dist/ink/searchHighlight.d.ts.map +1 -0
- package/dist/ink/searchHighlight.js +82 -0
- package/dist/ink/searchHighlight.js.map +1 -0
- package/dist/ink/selection.d.ts +230 -0
- package/dist/ink/selection.d.ts.map +1 -0
- package/dist/ink/selection.js +814 -0
- package/dist/ink/selection.js.map +1 -0
- package/dist/ink/squash-text-nodes.d.ts +23 -0
- package/dist/ink/squash-text-nodes.d.ts.map +1 -0
- package/dist/ink/squash-text-nodes.js +60 -0
- package/dist/ink/squash-text-nodes.js.map +1 -0
- package/dist/ink/stringWidth.d.ts +2 -0
- package/dist/ink/stringWidth.d.ts.map +1 -0
- package/dist/ink/stringWidth.js +207 -0
- package/dist/ink/stringWidth.js.map +1 -0
- package/dist/ink/styles.d.ts +307 -0
- package/dist/ink/styles.d.ts.map +1 -0
- package/dist/ink/styles.js +302 -0
- package/dist/ink/styles.js.map +1 -0
- package/dist/ink/supports-hyperlinks.d.ts +14 -0
- package/dist/ink/supports-hyperlinks.d.ts.map +1 -0
- package/dist/ink/supports-hyperlinks.js +48 -0
- package/dist/ink/supports-hyperlinks.js.map +1 -0
- package/dist/ink/tabstops.d.ts +2 -0
- package/dist/ink/tabstops.d.ts.map +1 -0
- package/dist/ink/tabstops.js +43 -0
- package/dist/ink/tabstops.js.map +1 -0
- package/dist/ink/terminal-focus-state.d.ts +7 -0
- package/dist/ink/terminal-focus-state.d.ts.map +1 -0
- package/dist/ink/terminal-focus-state.js +43 -0
- package/dist/ink/terminal-focus-state.js.map +1 -0
- package/dist/ink/terminal-querier.d.ts +130 -0
- package/dist/ink/terminal-querier.d.ts.map +1 -0
- package/dist/ink/terminal-querier.js +184 -0
- package/dist/ink/terminal-querier.js.map +1 -0
- package/dist/ink/terminal.d.ts +56 -0
- package/dist/ink/terminal.d.ts.map +1 -0
- package/dist/ink/terminal.js +249 -0
- package/dist/ink/terminal.js.map +1 -0
- package/dist/ink/termio/csi.d.ts +166 -0
- package/dist/ink/termio/csi.d.ts.map +1 -0
- package/dist/ink/termio/csi.js +285 -0
- package/dist/ink/termio/csi.js.map +1 -0
- package/dist/ink/termio/dec.d.ts +38 -0
- package/dist/ink/termio/dec.d.ts.map +1 -0
- package/dist/ink/termio/dec.js +59 -0
- package/dist/ink/termio/dec.js.map +1 -0
- package/dist/ink/termio.d.ts +25 -0
- package/dist/ink/termio.d.ts.map +1 -0
- package/dist/ink/termio.js +32 -0
- package/dist/ink/termio.js.map +1 -0
- package/dist/ink/useTerminalNotification.d.ts +27 -0
- package/dist/ink/useTerminalNotification.d.ts.map +1 -0
- package/dist/ink/useTerminalNotification.js +62 -0
- package/dist/ink/useTerminalNotification.js.map +1 -0
- package/dist/ink/warn.d.ts +2 -0
- package/dist/ink/warn.d.ts.map +1 -0
- package/dist/ink/warn.js +14 -0
- package/dist/ink/warn.js.map +1 -0
- package/dist/ink/widest-line.d.ts +2 -0
- package/dist/ink/widest-line.d.ts.map +1 -0
- package/dist/ink/widest-line.js +18 -0
- package/dist/ink/widest-line.js.map +1 -0
- package/dist/ink/wrap-text.d.ts +3 -0
- package/dist/ink/wrap-text.d.ts.map +1 -0
- package/dist/ink/wrap-text.js +61 -0
- package/dist/ink/wrap-text.js.map +1 -0
- package/dist/ink/wrapAnsi.d.ts +8 -0
- package/dist/ink/wrapAnsi.d.ts.map +1 -0
- package/dist/ink/wrapAnsi.js +13 -0
- package/dist/ink/wrapAnsi.js.map +1 -0
- package/dist/memory/embeddings.d.ts +33 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +123 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/index.d.ts +14 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +31 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/prompts.d.ts +12 -0
- package/dist/memory/prompts.d.ts.map +1 -0
- package/dist/memory/prompts.js +117 -0
- package/dist/memory/prompts.js.map +1 -0
- package/dist/memory/semantic-search.d.ts +45 -0
- package/dist/memory/semantic-search.d.ts.map +1 -0
- package/dist/memory/semantic-search.js +112 -0
- package/dist/memory/semantic-search.js.map +1 -0
- package/dist/memory/storage.d.ts +79 -0
- package/dist/memory/storage.d.ts.map +1 -0
- package/dist/memory/storage.js +285 -0
- package/dist/memory/storage.js.map +1 -0
- package/dist/memory/store.d.ts +103 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +226 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/types.d.ts +40 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +71 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/memory/validation.d.ts +28 -0
- package/dist/memory/validation.d.ts.map +1 -0
- package/dist/memory/validation.js +147 -0
- package/dist/memory/validation.js.map +1 -0
- package/dist/memory/vector-store.d.ts +49 -0
- package/dist/memory/vector-store.d.ts.map +1 -0
- package/dist/memory/vector-store.js +259 -0
- package/dist/memory/vector-store.js.map +1 -0
- package/dist/screens/REPL.d.ts +21 -0
- package/dist/screens/REPL.d.ts.map +1 -0
- package/dist/screens/REPL.js +139 -0
- package/dist/screens/REPL.js.map +1 -0
- package/dist/services/agent-runner.d.ts +68 -0
- package/dist/services/agent-runner.d.ts.map +1 -0
- package/dist/services/agent-runner.js +186 -0
- package/dist/services/agent-runner.js.map +1 -0
- package/dist/services/atomic-write.d.ts +12 -0
- package/dist/services/atomic-write.d.ts.map +1 -0
- package/dist/services/atomic-write.js +27 -0
- package/dist/services/atomic-write.js.map +1 -0
- package/dist/services/config-dir.d.ts +55 -0
- package/dist/services/config-dir.d.ts.map +1 -0
- package/dist/services/config-dir.js +136 -0
- package/dist/services/config-dir.js.map +1 -0
- package/dist/services/config.d.ts +54 -0
- package/dist/services/config.d.ts.map +1 -0
- package/dist/services/config.js +98 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/file-glob.d.ts +26 -0
- package/dist/services/file-glob.d.ts.map +1 -0
- package/dist/services/file-glob.js +134 -0
- package/dist/services/file-glob.js.map +1 -0
- package/dist/services/global-config.d.ts +109 -0
- package/dist/services/global-config.d.ts.map +1 -0
- package/dist/services/global-config.js +211 -0
- package/dist/services/global-config.js.map +1 -0
- package/dist/services/llm.d.ts +139 -0
- package/dist/services/llm.d.ts.map +1 -0
- package/dist/services/llm.js +376 -0
- package/dist/services/llm.js.map +1 -0
- package/dist/services/memory.d.ts +39 -0
- package/dist/services/memory.d.ts.map +1 -0
- package/dist/services/memory.js +88 -0
- package/dist/services/memory.js.map +1 -0
- package/dist/services/session-storage.d.ts +136 -0
- package/dist/services/session-storage.d.ts.map +1 -0
- package/dist/services/session-storage.js +304 -0
- package/dist/services/session-storage.js.map +1 -0
- package/dist/services/task-manager.d.ts +154 -0
- package/dist/services/task-manager.d.ts.map +1 -0
- package/dist/services/task-manager.js +288 -0
- package/dist/services/task-manager.js.map +1 -0
- package/dist/services/yaml-config.d.ts +57 -0
- package/dist/services/yaml-config.d.ts.map +1 -0
- package/dist/services/yaml-config.js +176 -0
- package/dist/services/yaml-config.js.map +1 -0
- package/dist/skills/discovery.d.ts +22 -0
- package/dist/skills/discovery.d.ts.map +1 -0
- package/dist/skills/discovery.js +75 -0
- package/dist/skills/discovery.js.map +1 -0
- package/dist/skills/index.d.ts +10 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +26 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/loader.d.ts +48 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +231 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/registry.d.ts +37 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +134 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/types.d.ts +89 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +24 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/tools/bash_security.d.ts +64 -0
- package/dist/tools/bash_security.d.ts.map +1 -0
- package/dist/tools/bash_security.js +291 -0
- package/dist/tools/bash_security.js.map +1 -0
- package/dist/tools/index.d.ts +23 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +965 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/mcp.d.ts +72 -0
- package/dist/tools/mcp.d.ts.map +1 -0
- package/dist/tools/mcp.js +422 -0
- package/dist/tools/mcp.js.map +1 -0
- package/dist/tools/plan.d.ts +18 -0
- package/dist/tools/plan.d.ts.map +1 -0
- package/dist/tools/plan.js +75 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/todo.d.ts +18 -0
- package/dist/tools/todo.d.ts.map +1 -0
- package/dist/tools/todo.js +153 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/web.d.ts +13 -0
- package/dist/tools/web.d.ts.map +1 -0
- package/dist/tools/web.js +377 -0
- package/dist/tools/web.js.map +1 -0
- package/dist/ui/box.d.ts +56 -0
- package/dist/ui/box.d.ts.map +1 -0
- package/dist/ui/box.js +241 -0
- package/dist/ui/box.js.map +1 -0
- package/dist/ui/command-panel.d.ts +55 -0
- package/dist/ui/command-panel.d.ts.map +1 -0
- package/dist/ui/command-panel.js +212 -0
- package/dist/ui/command-panel.js.map +1 -0
- package/dist/ui/file-completion.d.ts +62 -0
- package/dist/ui/file-completion.d.ts.map +1 -0
- package/dist/ui/file-completion.js +209 -0
- package/dist/ui/file-completion.js.map +1 -0
- package/dist/ui/markdown.d.ts +12 -0
- package/dist/ui/markdown.d.ts.map +1 -0
- package/dist/ui/markdown.js +215 -0
- package/dist/ui/markdown.js.map +1 -0
- package/dist/ui/multiline-input.d.ts +47 -0
- package/dist/ui/multiline-input.d.ts.map +1 -0
- package/dist/ui/multiline-input.js +94 -0
- package/dist/ui/multiline-input.js.map +1 -0
- package/dist/ui/status-bar.d.ts +33 -0
- package/dist/ui/status-bar.d.ts.map +1 -0
- package/dist/ui/status-bar.js +96 -0
- package/dist/ui/status-bar.js.map +1 -0
- package/dist/ui/stream-markdown.d.ts +35 -0
- package/dist/ui/stream-markdown.d.ts.map +1 -0
- package/dist/ui/stream-markdown.js +138 -0
- package/dist/ui/stream-markdown.js.map +1 -0
- package/dist/ui/suggestions.d.ts +35 -0
- package/dist/ui/suggestions.d.ts.map +1 -0
- package/dist/ui/suggestions.js +118 -0
- package/dist/ui/suggestions.js.map +1 -0
- package/dist/ui/tool-preview.d.ts +34 -0
- package/dist/ui/tool-preview.d.ts.map +1 -0
- package/dist/ui/tool-preview.js +128 -0
- package/dist/ui/tool-preview.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,965 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* openhorse - 工具集
|
|
4
|
+
*
|
|
5
|
+
* 定义 Agent 可用的工具(Tool System v2):
|
|
6
|
+
* - read_file: 读取文件内容
|
|
7
|
+
* - write_file: 写入文件
|
|
8
|
+
* - list_files: 列出目录
|
|
9
|
+
* - exec_command: 执行 shell 命令
|
|
10
|
+
*
|
|
11
|
+
* 使用 buildTool() 工厂模式。
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.DEFAULT_SANDBOX_OPTIONS = exports.wrapForSandbox = exports.assessCommandSecurity = exports.isPotentiallyDestructive = exports.checkDangerousCommand = exports.isReadOnlyCommand = exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = exports.DANGEROUS_PATTERNS = exports.READ_ONLY_COMMANDS = exports.TOOLS = void 0;
|
|
15
|
+
exports.executeTool = executeTool;
|
|
16
|
+
exports.getToolNames = getToolNames;
|
|
17
|
+
const child_process_1 = require("child_process");
|
|
18
|
+
const fs_1 = require("fs");
|
|
19
|
+
const path_1 = require("path");
|
|
20
|
+
const readline_1 = require("readline");
|
|
21
|
+
const tool_1 = require("../framework/tool");
|
|
22
|
+
const memory_1 = require("../memory");
|
|
23
|
+
const semantic_search_1 = require("../memory/semantic-search");
|
|
24
|
+
const session_storage_1 = require("../services/session-storage");
|
|
25
|
+
const web_1 = require("./web");
|
|
26
|
+
const mcp_1 = require("./mcp");
|
|
27
|
+
const todo_1 = require("./todo");
|
|
28
|
+
const plan_1 = require("./plan");
|
|
29
|
+
const bash_security_1 = require("./bash_security");
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// 工具集
|
|
32
|
+
// ============================================================================
|
|
33
|
+
exports.TOOLS = [
|
|
34
|
+
// Web tools (P0)
|
|
35
|
+
...web_1.WEB_TOOLS,
|
|
36
|
+
// MCP tools (P0)
|
|
37
|
+
...mcp_1.MCP_TOOLS,
|
|
38
|
+
// Todo tools (P1)
|
|
39
|
+
...todo_1.TODO_TOOLS,
|
|
40
|
+
// Plan mode tools (P1)
|
|
41
|
+
...plan_1.PLAN_TOOLS,
|
|
42
|
+
// File tools
|
|
43
|
+
(0, tool_1.buildTool)({
|
|
44
|
+
name: 'read_file',
|
|
45
|
+
description: '读取文件的全部内容。返回文件内容字符串。',
|
|
46
|
+
parameters: {
|
|
47
|
+
type: 'object',
|
|
48
|
+
properties: {
|
|
49
|
+
path: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: '文件路径(绝对路径或相对路径)',
|
|
52
|
+
},
|
|
53
|
+
maxLines: {
|
|
54
|
+
type: 'number',
|
|
55
|
+
description: '最大读取行数(可选,默认 500 行)',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
required: ['path'],
|
|
59
|
+
},
|
|
60
|
+
execute: async (args) => {
|
|
61
|
+
// Ensure path is a valid string
|
|
62
|
+
const path = args.path;
|
|
63
|
+
if (!path || typeof path !== 'string') {
|
|
64
|
+
return { success: false, output: '', error: 'read_file requires a path parameter' };
|
|
65
|
+
}
|
|
66
|
+
return readFileSync_(path, args.maxLines);
|
|
67
|
+
},
|
|
68
|
+
isReadOnly: () => true,
|
|
69
|
+
userFacingName: (args) => `Read ${args.path}`,
|
|
70
|
+
}),
|
|
71
|
+
(0, tool_1.buildTool)({
|
|
72
|
+
name: 'write_file',
|
|
73
|
+
description: '将内容写入文件。如果文件不存在则创建,存在则覆盖。',
|
|
74
|
+
parameters: {
|
|
75
|
+
type: 'object',
|
|
76
|
+
properties: {
|
|
77
|
+
path: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
description: '文件路径(绝对路径或相对路径)',
|
|
80
|
+
},
|
|
81
|
+
content: {
|
|
82
|
+
type: 'string',
|
|
83
|
+
description: '要写入的文件内容',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
required: ['path', 'content'],
|
|
87
|
+
},
|
|
88
|
+
execute: async (args) => {
|
|
89
|
+
// Ensure path and content are valid strings
|
|
90
|
+
const path = args.path;
|
|
91
|
+
const content = args.content;
|
|
92
|
+
if (!path || typeof path !== 'string') {
|
|
93
|
+
return { success: false, output: '', error: 'write_file requires a path parameter' };
|
|
94
|
+
}
|
|
95
|
+
if (!content || typeof content !== 'string') {
|
|
96
|
+
return { success: false, output: '', error: 'write_file requires a content parameter' };
|
|
97
|
+
}
|
|
98
|
+
return writeFileSync_(path, content);
|
|
99
|
+
},
|
|
100
|
+
isDestructive: () => true,
|
|
101
|
+
checkPermissions: (args, context) => {
|
|
102
|
+
// Destructive operation - ask for confirmation in default mode
|
|
103
|
+
return { behavior: 'ask', reason: 'Write operation may modify existing files' };
|
|
104
|
+
},
|
|
105
|
+
userFacingName: (args) => `Write ${args.path}`,
|
|
106
|
+
}),
|
|
107
|
+
(0, tool_1.buildTool)({
|
|
108
|
+
name: 'list_files',
|
|
109
|
+
description: '列出指定目录中的文件和子目录。支持控制递归深度。',
|
|
110
|
+
parameters: {
|
|
111
|
+
type: 'object',
|
|
112
|
+
properties: {
|
|
113
|
+
path: {
|
|
114
|
+
type: 'string',
|
|
115
|
+
description: '目录路径(绝对路径或相对路径)',
|
|
116
|
+
},
|
|
117
|
+
maxDepth: {
|
|
118
|
+
type: 'number',
|
|
119
|
+
description: '最大递归深度(可选,默认 2)',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
required: ['path'],
|
|
123
|
+
},
|
|
124
|
+
execute: async (args) => {
|
|
125
|
+
// Ensure path is a valid string
|
|
126
|
+
const path = args.path;
|
|
127
|
+
if (!path || typeof path !== 'string') {
|
|
128
|
+
return { success: false, output: '', error: 'list_files requires a path parameter' };
|
|
129
|
+
}
|
|
130
|
+
return listFiles_(path, args.maxDepth);
|
|
131
|
+
},
|
|
132
|
+
isReadOnly: () => true,
|
|
133
|
+
isConcurrencySafe: () => true,
|
|
134
|
+
userFacingName: (args) => `List ${args.path}`,
|
|
135
|
+
}),
|
|
136
|
+
(0, tool_1.buildTool)({
|
|
137
|
+
name: 'exec_command',
|
|
138
|
+
description: '执行一个 shell 命令。返回 stdout 和 stderr。',
|
|
139
|
+
parameters: {
|
|
140
|
+
type: 'object',
|
|
141
|
+
properties: {
|
|
142
|
+
command: {
|
|
143
|
+
type: 'string',
|
|
144
|
+
description: '要执行的 shell 命令',
|
|
145
|
+
},
|
|
146
|
+
cwd: {
|
|
147
|
+
type: 'string',
|
|
148
|
+
description: '工作目录(可选,默认当前目录)',
|
|
149
|
+
},
|
|
150
|
+
timeout: {
|
|
151
|
+
type: 'number',
|
|
152
|
+
description: '超时时间 ms(可选,默认 30000)',
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
required: ['command'],
|
|
156
|
+
},
|
|
157
|
+
execute: async (args) => {
|
|
158
|
+
// Ensure command is a valid string
|
|
159
|
+
const command = args.command;
|
|
160
|
+
if (!command || typeof command !== 'string') {
|
|
161
|
+
return { success: false, output: '', error: 'exec_command requires a command parameter' };
|
|
162
|
+
}
|
|
163
|
+
return execCommand_(command, args.cwd, args.timeout);
|
|
164
|
+
},
|
|
165
|
+
isDestructive: (args) => {
|
|
166
|
+
const cmd = args.command || '';
|
|
167
|
+
return /(rm\s+-rf|mkfs|dd\s)/.test(cmd);
|
|
168
|
+
},
|
|
169
|
+
checkPermissions: (args, context) => {
|
|
170
|
+
const cmd = args.command || '';
|
|
171
|
+
// Use the bash_security module for comprehensive checks
|
|
172
|
+
const security = (0, bash_security_1.assessCommandSecurity)(cmd);
|
|
173
|
+
if (security.level === 'blocked') {
|
|
174
|
+
return { behavior: 'deny', reason: security.reason || `Command blocked by safety policy: ${cmd.slice(0, 50)}` };
|
|
175
|
+
}
|
|
176
|
+
if (security.level === 'safe' && security.isReadOnly) {
|
|
177
|
+
return { behavior: 'allow' };
|
|
178
|
+
}
|
|
179
|
+
if (security.level === 'caution') {
|
|
180
|
+
return { behavior: 'ask', reason: security.reason || 'Command requires confirmation' };
|
|
181
|
+
}
|
|
182
|
+
// Default: ask for confirmation
|
|
183
|
+
return { behavior: 'ask', reason: 'Command requires confirmation' };
|
|
184
|
+
},
|
|
185
|
+
isReadOnly: (args) => {
|
|
186
|
+
const cmd = args.command || '';
|
|
187
|
+
return (0, bash_security_1.isReadOnlyCommand)(cmd);
|
|
188
|
+
},
|
|
189
|
+
userFacingName: (args) => `Exec ${args.command?.slice(0, 60) || ''}`,
|
|
190
|
+
}),
|
|
191
|
+
(0, tool_1.buildTool)({
|
|
192
|
+
name: 'edit_file',
|
|
193
|
+
description: '对文件进行精确字符串替换。old_string 必须在文件中唯一匹配,否则拒绝执行。使用 replace_all 可替换所有匹配。',
|
|
194
|
+
parameters: {
|
|
195
|
+
type: 'object',
|
|
196
|
+
properties: {
|
|
197
|
+
path: {
|
|
198
|
+
type: 'string',
|
|
199
|
+
description: '文件路径(绝对路径或相对路径)',
|
|
200
|
+
},
|
|
201
|
+
old_string: {
|
|
202
|
+
type: 'string',
|
|
203
|
+
description: '要替换的字符串(必须精确匹配)',
|
|
204
|
+
},
|
|
205
|
+
new_string: {
|
|
206
|
+
type: 'string',
|
|
207
|
+
description: '替换后的字符串',
|
|
208
|
+
},
|
|
209
|
+
replace_all: {
|
|
210
|
+
type: 'boolean',
|
|
211
|
+
description: '是否替换所有匹配(可选,默认 false)',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
required: ['path', 'old_string', 'new_string'],
|
|
215
|
+
},
|
|
216
|
+
execute: async (args) => {
|
|
217
|
+
// Ensure required parameters are valid strings
|
|
218
|
+
const path = args.path;
|
|
219
|
+
const old_string = args.old_string;
|
|
220
|
+
const new_string = args.new_string;
|
|
221
|
+
if (!path || typeof path !== 'string') {
|
|
222
|
+
return { success: false, output: '', error: 'edit_file requires a path parameter' };
|
|
223
|
+
}
|
|
224
|
+
if (!old_string || typeof old_string !== 'string') {
|
|
225
|
+
return { success: false, output: '', error: 'edit_file requires an old_string parameter' };
|
|
226
|
+
}
|
|
227
|
+
if (!new_string || typeof new_string !== 'string') {
|
|
228
|
+
return { success: false, output: '', error: 'edit_file requires a new_string parameter' };
|
|
229
|
+
}
|
|
230
|
+
return editFile_(path, old_string, new_string, args.replace_all);
|
|
231
|
+
},
|
|
232
|
+
isDestructive: () => true,
|
|
233
|
+
checkPermissions: (args, context) => {
|
|
234
|
+
return { behavior: 'ask', reason: 'Edit operation modifies file contents' };
|
|
235
|
+
},
|
|
236
|
+
userFacingName: (args) => `Edit ${args.path}`,
|
|
237
|
+
}),
|
|
238
|
+
(0, tool_1.buildTool)({
|
|
239
|
+
name: 'glob',
|
|
240
|
+
description: '使用 glob 模式搜索文件。支持 **(递归)、*(任意字符)、?(单个字符)等通配符。',
|
|
241
|
+
parameters: {
|
|
242
|
+
type: 'object',
|
|
243
|
+
properties: {
|
|
244
|
+
pattern: {
|
|
245
|
+
type: 'string',
|
|
246
|
+
description: 'Glob 模式(如 **/*.ts, src/**/*.js)',
|
|
247
|
+
},
|
|
248
|
+
path: {
|
|
249
|
+
type: 'string',
|
|
250
|
+
description: '搜索起始目录(可选,默认当前目录)',
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
required: ['pattern'],
|
|
254
|
+
},
|
|
255
|
+
execute: async (args) => {
|
|
256
|
+
// Ensure pattern is a valid string
|
|
257
|
+
const pattern = args.pattern;
|
|
258
|
+
if (!pattern || typeof pattern !== 'string') {
|
|
259
|
+
return { success: false, output: '', error: 'glob requires a pattern parameter' };
|
|
260
|
+
}
|
|
261
|
+
return glob_(pattern, args.path);
|
|
262
|
+
},
|
|
263
|
+
isReadOnly: () => true,
|
|
264
|
+
isConcurrencySafe: () => true,
|
|
265
|
+
userFacingName: (args) => `Glob ${args.pattern}`,
|
|
266
|
+
}),
|
|
267
|
+
(0, tool_1.buildTool)({
|
|
268
|
+
name: 'grep',
|
|
269
|
+
description: '在文件中搜索正则表达式模式。返回匹配的文件路径和行内容。',
|
|
270
|
+
parameters: {
|
|
271
|
+
type: 'object',
|
|
272
|
+
properties: {
|
|
273
|
+
pattern: {
|
|
274
|
+
type: 'string',
|
|
275
|
+
description: '正则表达式模式',
|
|
276
|
+
},
|
|
277
|
+
path: {
|
|
278
|
+
type: 'string',
|
|
279
|
+
description: '搜索路径(可选,默认当前目录)',
|
|
280
|
+
},
|
|
281
|
+
glob: {
|
|
282
|
+
type: 'string',
|
|
283
|
+
description: '文件过滤模式(可选,如 *.ts)',
|
|
284
|
+
},
|
|
285
|
+
context: {
|
|
286
|
+
type: 'number',
|
|
287
|
+
description: '上下文行数(可选,默认 0)',
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
required: ['pattern'],
|
|
291
|
+
},
|
|
292
|
+
execute: async (args) => {
|
|
293
|
+
// Ensure pattern is a valid string
|
|
294
|
+
const pattern = args.pattern;
|
|
295
|
+
if (!pattern || typeof pattern !== 'string') {
|
|
296
|
+
return { success: false, output: '', error: 'grep requires a pattern parameter' };
|
|
297
|
+
}
|
|
298
|
+
return grep_(pattern, args.path, args.glob, args.context);
|
|
299
|
+
},
|
|
300
|
+
isReadOnly: () => true,
|
|
301
|
+
isConcurrencySafe: () => true,
|
|
302
|
+
userFacingName: (args) => `Grep ${args.pattern}`,
|
|
303
|
+
}),
|
|
304
|
+
// Memory tools
|
|
305
|
+
(0, tool_1.buildTool)({
|
|
306
|
+
name: 'memory_save',
|
|
307
|
+
description: 'Save a memory entry to the persistent memory system. Memories help tailor behavior to user preferences.',
|
|
308
|
+
parameters: {
|
|
309
|
+
type: 'object',
|
|
310
|
+
properties: {
|
|
311
|
+
name: {
|
|
312
|
+
type: 'string',
|
|
313
|
+
description: 'Memory name (kebab-case, e.g., "user-role", "feedback-style")',
|
|
314
|
+
},
|
|
315
|
+
type: {
|
|
316
|
+
type: 'string',
|
|
317
|
+
enum: ['user', 'feedback', 'project', 'reference'],
|
|
318
|
+
description: 'Memory type',
|
|
319
|
+
},
|
|
320
|
+
description: {
|
|
321
|
+
type: 'string',
|
|
322
|
+
description: 'One-line description for memory index',
|
|
323
|
+
},
|
|
324
|
+
content: {
|
|
325
|
+
type: 'string',
|
|
326
|
+
description: 'Memory content. For feedback/project: use rule + Why + How to apply structure',
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
required: ['name', 'type', 'content'],
|
|
330
|
+
},
|
|
331
|
+
execute: async (args) => {
|
|
332
|
+
const name = args.name;
|
|
333
|
+
const type = args.type;
|
|
334
|
+
const content = args.content;
|
|
335
|
+
const description = args.description || content.slice(0, 80);
|
|
336
|
+
if (!name || typeof name !== 'string') {
|
|
337
|
+
return { success: false, output: '', error: 'memory_save requires a name parameter' };
|
|
338
|
+
}
|
|
339
|
+
if (!type || !['user', 'feedback', 'project', 'reference'].includes(type)) {
|
|
340
|
+
return { success: false, output: '', error: 'memory_save requires a valid type: user, feedback, project, or reference' };
|
|
341
|
+
}
|
|
342
|
+
if (!content || typeof content !== 'string') {
|
|
343
|
+
return { success: false, output: '', error: 'memory_save requires a content parameter' };
|
|
344
|
+
}
|
|
345
|
+
try {
|
|
346
|
+
const projectPath = process.cwd();
|
|
347
|
+
const entry = {
|
|
348
|
+
name,
|
|
349
|
+
type,
|
|
350
|
+
description,
|
|
351
|
+
content,
|
|
352
|
+
createdAt: Date.now(),
|
|
353
|
+
updatedAt: Date.now(),
|
|
354
|
+
};
|
|
355
|
+
if ((0, semantic_search_1.isSemanticEnabled)()) {
|
|
356
|
+
// saveAndIndex internally calls saveMemory + vectorStore.upsert
|
|
357
|
+
await (0, semantic_search_1.getSemanticSearchService)().saveAndIndex(entry, projectPath);
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
(0, memory_1.saveMemory)(entry, projectPath);
|
|
361
|
+
}
|
|
362
|
+
return { success: true, output: `Saved memory: ${name} (${type})` };
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
return { success: false, output: '', error: err.message };
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
isReadOnly: () => false,
|
|
369
|
+
userFacingName: (args) => `Memory save ${args.name}`,
|
|
370
|
+
}),
|
|
371
|
+
(0, tool_1.buildTool)({
|
|
372
|
+
name: 'memory_recall',
|
|
373
|
+
description: 'Recall memories from the memory system. Returns matching memories or all if no query.',
|
|
374
|
+
parameters: {
|
|
375
|
+
type: 'object',
|
|
376
|
+
properties: {
|
|
377
|
+
query: {
|
|
378
|
+
type: 'string',
|
|
379
|
+
description: 'Search query (optional, returns all if empty)',
|
|
380
|
+
},
|
|
381
|
+
type: {
|
|
382
|
+
type: 'string',
|
|
383
|
+
enum: ['user', 'feedback', 'project', 'reference'],
|
|
384
|
+
description: 'Filter by memory type (optional)',
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
required: [],
|
|
388
|
+
},
|
|
389
|
+
execute: async (args) => {
|
|
390
|
+
try {
|
|
391
|
+
const projectPath = process.cwd();
|
|
392
|
+
const query = args.query || '';
|
|
393
|
+
const type = args.type;
|
|
394
|
+
let memories;
|
|
395
|
+
if (query && (0, semantic_search_1.isSemanticEnabled)()) {
|
|
396
|
+
// Semantic path: ask the vector store, then fall back to keywords if it
|
|
397
|
+
// returns nothing (e.g. embedding provider unreachable, empty index)
|
|
398
|
+
try {
|
|
399
|
+
const result = await (0, semantic_search_1.getSemanticSearchService)().search({
|
|
400
|
+
query,
|
|
401
|
+
projectPath,
|
|
402
|
+
type,
|
|
403
|
+
});
|
|
404
|
+
memories = result.memories.map(m => ({
|
|
405
|
+
name: m.name,
|
|
406
|
+
type: m.type,
|
|
407
|
+
description: m.description,
|
|
408
|
+
content: m.content,
|
|
409
|
+
createdAt: m.createdAt,
|
|
410
|
+
updatedAt: m.createdAt,
|
|
411
|
+
}));
|
|
412
|
+
if (memories.length === 0) {
|
|
413
|
+
memories = (0, memory_1.searchMemories)(query, projectPath);
|
|
414
|
+
if (type)
|
|
415
|
+
memories = memories.filter(m => m.type === type);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
memories = (0, memory_1.searchMemories)(query, projectPath);
|
|
420
|
+
if (type)
|
|
421
|
+
memories = memories.filter(m => m.type === type);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
else if (type) {
|
|
425
|
+
memories = (0, memory_1.loadAllMemories)(projectPath).filter(m => m.type === type);
|
|
426
|
+
}
|
|
427
|
+
else if (query) {
|
|
428
|
+
memories = (0, memory_1.searchMemories)(query, projectPath);
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
memories = (0, memory_1.loadAllMemories)(projectPath);
|
|
432
|
+
}
|
|
433
|
+
if (memories.length === 0) {
|
|
434
|
+
return { success: true, output: 'No memories found' };
|
|
435
|
+
}
|
|
436
|
+
const lines = [];
|
|
437
|
+
for (const mem of memories) {
|
|
438
|
+
lines.push(`## ${mem.name} (${mem.type})`);
|
|
439
|
+
lines.push(mem.description);
|
|
440
|
+
lines.push(mem.content);
|
|
441
|
+
lines.push('');
|
|
442
|
+
}
|
|
443
|
+
return { success: true, output: lines.join('\n') };
|
|
444
|
+
}
|
|
445
|
+
catch (err) {
|
|
446
|
+
return { success: false, output: '', error: err.message };
|
|
447
|
+
}
|
|
448
|
+
},
|
|
449
|
+
isReadOnly: () => true,
|
|
450
|
+
userFacingName: (args) => `Memory recall ${args.query || 'all'}`,
|
|
451
|
+
}),
|
|
452
|
+
(0, tool_1.buildTool)({
|
|
453
|
+
name: 'memory_forget',
|
|
454
|
+
description: 'Delete a memory entry from the memory system.',
|
|
455
|
+
parameters: {
|
|
456
|
+
type: 'object',
|
|
457
|
+
properties: {
|
|
458
|
+
name: {
|
|
459
|
+
type: 'string',
|
|
460
|
+
description: 'Memory name to delete',
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
required: ['name'],
|
|
464
|
+
},
|
|
465
|
+
execute: async (args) => {
|
|
466
|
+
const name = args.name;
|
|
467
|
+
if (!name || typeof name !== 'string') {
|
|
468
|
+
return { success: false, output: '', error: 'memory_forget requires a name parameter' };
|
|
469
|
+
}
|
|
470
|
+
try {
|
|
471
|
+
const projectPath = process.cwd();
|
|
472
|
+
const existing = (0, memory_1.loadMemory)(name, projectPath);
|
|
473
|
+
if (!existing) {
|
|
474
|
+
return { success: false, output: '', error: `Memory not found: ${name}` };
|
|
475
|
+
}
|
|
476
|
+
(0, memory_1.deleteMemory)(name, projectPath);
|
|
477
|
+
if ((0, semantic_search_1.isSemanticEnabled)()) {
|
|
478
|
+
try {
|
|
479
|
+
const { getVectorStore } = require('../memory/vector-store');
|
|
480
|
+
getVectorStore().delete(name);
|
|
481
|
+
}
|
|
482
|
+
catch {
|
|
483
|
+
// Vector store cleanup is best-effort
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return { success: true, output: `Deleted memory: ${name}` };
|
|
487
|
+
}
|
|
488
|
+
catch (err) {
|
|
489
|
+
return { success: false, output: '', error: err.message };
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
isReadOnly: () => false,
|
|
493
|
+
userFacingName: (args) => `Memory forget ${args.name}`,
|
|
494
|
+
}),
|
|
495
|
+
// History search tool
|
|
496
|
+
(0, tool_1.buildTool)({
|
|
497
|
+
name: 'history_search',
|
|
498
|
+
description: 'Search previous tool operations in current or past sessions. Helps find what was done before.',
|
|
499
|
+
parameters: {
|
|
500
|
+
type: 'object',
|
|
501
|
+
properties: {
|
|
502
|
+
query: {
|
|
503
|
+
type: 'string',
|
|
504
|
+
description: 'Search query (tool name, file path, keyword)',
|
|
505
|
+
},
|
|
506
|
+
sessionId: {
|
|
507
|
+
type: 'string',
|
|
508
|
+
description: 'Session ID to search (optional, defaults to searching recent sessions)',
|
|
509
|
+
},
|
|
510
|
+
limit: {
|
|
511
|
+
type: 'number',
|
|
512
|
+
description: 'Max results (optional, default 10)',
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
required: ['query'],
|
|
516
|
+
},
|
|
517
|
+
execute: async (args) => {
|
|
518
|
+
const query = args.query;
|
|
519
|
+
if (!query || typeof query !== 'string') {
|
|
520
|
+
return { success: false, output: '', error: 'history_search requires a query parameter' };
|
|
521
|
+
}
|
|
522
|
+
try {
|
|
523
|
+
const limit = args.limit || 10;
|
|
524
|
+
const sessionId = args.sessionId;
|
|
525
|
+
// If sessionId provided, search that session; otherwise search all recent sessions
|
|
526
|
+
const sessions = sessionId
|
|
527
|
+
? [(0, session_storage_1.loadSessionMeta)(sessionId)].filter(Boolean)
|
|
528
|
+
: (0, session_storage_1.listSessions)(5);
|
|
529
|
+
const results = [];
|
|
530
|
+
for (const session of sessions) {
|
|
531
|
+
if (!session)
|
|
532
|
+
continue;
|
|
533
|
+
const messages = (0, session_storage_1.readSessionMessages)(session.id);
|
|
534
|
+
// Search through messages for tool calls matching query
|
|
535
|
+
for (let i = 0; i < messages.length; i++) {
|
|
536
|
+
const msg = messages[i];
|
|
537
|
+
if (msg.role === 'assistant' && msg.tool_calls) {
|
|
538
|
+
for (const tc of msg.tool_calls) {
|
|
539
|
+
// Match tool name or arguments content
|
|
540
|
+
const matchesQuery = tc.function.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
541
|
+
tc.function.arguments.toLowerCase().includes(query.toLowerCase());
|
|
542
|
+
if (matchesQuery) {
|
|
543
|
+
// Find corresponding tool result
|
|
544
|
+
const nextMsg = messages[i + 1];
|
|
545
|
+
const resultPreview = nextMsg?.role === 'tool' && nextMsg.toolCallId === tc.id
|
|
546
|
+
? nextMsg.content.slice(0, 200)
|
|
547
|
+
: '(no result)';
|
|
548
|
+
results.push({
|
|
549
|
+
sessionId: session.id.slice(0, 8),
|
|
550
|
+
tool: tc.function.name,
|
|
551
|
+
args: tc.function.arguments.slice(0, 100),
|
|
552
|
+
resultPreview,
|
|
553
|
+
timestamp: msg.timestamp,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// Sort by timestamp (newest first) and limit
|
|
561
|
+
results.sort((a, b) => b.timestamp - a.timestamp);
|
|
562
|
+
const limited = results.slice(0, limit);
|
|
563
|
+
if (limited.length === 0) {
|
|
564
|
+
return { success: true, output: 'No matching tool operations found' };
|
|
565
|
+
}
|
|
566
|
+
const lines = [];
|
|
567
|
+
lines.push(`Found ${limited.length} matching operations:`);
|
|
568
|
+
lines.push('');
|
|
569
|
+
for (const r of limited) {
|
|
570
|
+
lines.push(`Session ${r.sessionId}: ${r.tool}`);
|
|
571
|
+
lines.push(` Args: ${r.args}`);
|
|
572
|
+
lines.push(` Result: ${r.resultPreview.slice(0, 100)}...`);
|
|
573
|
+
lines.push('');
|
|
574
|
+
}
|
|
575
|
+
return { success: true, output: lines.join('\n') };
|
|
576
|
+
}
|
|
577
|
+
catch (err) {
|
|
578
|
+
return { success: false, output: '', error: err.message };
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
isReadOnly: () => true,
|
|
582
|
+
userFacingName: (args) => `History search ${args.query}`,
|
|
583
|
+
}),
|
|
584
|
+
];
|
|
585
|
+
// ============================================================================
|
|
586
|
+
// 工具实现
|
|
587
|
+
// ============================================================================
|
|
588
|
+
/** 安全路径解析 — 防止路径遍历攻击 */
|
|
589
|
+
function safePath(input) {
|
|
590
|
+
const resolved = (0, path_1.resolve)(input);
|
|
591
|
+
const cwd = process.cwd();
|
|
592
|
+
if ((0, path_1.relative)(cwd, resolved).startsWith('..')) {
|
|
593
|
+
return cwd;
|
|
594
|
+
}
|
|
595
|
+
return resolved;
|
|
596
|
+
}
|
|
597
|
+
async function readFileSync_(path, maxLines) {
|
|
598
|
+
try {
|
|
599
|
+
const resolved = safePath(path);
|
|
600
|
+
if (!(0, fs_1.existsSync)(resolved)) {
|
|
601
|
+
return { success: false, output: '', error: `File not found: ${path}` };
|
|
602
|
+
}
|
|
603
|
+
if ((0, fs_1.statSync)(resolved).isDirectory()) {
|
|
604
|
+
return { success: false, output: '', error: `Path is a directory, not a file: ${path}` };
|
|
605
|
+
}
|
|
606
|
+
const content = (0, fs_1.readFileSync)(resolved, 'utf-8');
|
|
607
|
+
const lines = content.split('\n');
|
|
608
|
+
const limit = maxLines ?? 500;
|
|
609
|
+
if (lines.length > limit) {
|
|
610
|
+
return {
|
|
611
|
+
success: true,
|
|
612
|
+
output: lines.slice(0, limit).join('\n') + `\n\n[... truncated, ${lines.length - limit} more lines]`,
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
return { success: true, output: content };
|
|
616
|
+
}
|
|
617
|
+
catch (err) {
|
|
618
|
+
return { success: false, output: '', error: String(err.message) };
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
async function writeFileSync_(path, content) {
|
|
622
|
+
try {
|
|
623
|
+
const resolved = safePath(path);
|
|
624
|
+
(0, fs_1.writeFileSync)(resolved, content, 'utf-8');
|
|
625
|
+
return { success: true, output: `Wrote ${content.split('\n').length} lines to ${path}` };
|
|
626
|
+
}
|
|
627
|
+
catch (err) {
|
|
628
|
+
return { success: false, output: '', error: String(err.message) };
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
async function listFiles_(path, maxDepth) {
|
|
632
|
+
const resolved = safePath(path);
|
|
633
|
+
if (!(0, fs_1.existsSync)(resolved)) {
|
|
634
|
+
return { success: false, output: '', error: `Path not found: ${path}` };
|
|
635
|
+
}
|
|
636
|
+
if (!(0, fs_1.statSync)(resolved).isDirectory()) {
|
|
637
|
+
return { success: true, output: path };
|
|
638
|
+
}
|
|
639
|
+
const depth = maxDepth ?? 2;
|
|
640
|
+
const results = [];
|
|
641
|
+
function walk(dir, currentDepth, prefix) {
|
|
642
|
+
if (currentDepth > depth)
|
|
643
|
+
return;
|
|
644
|
+
try {
|
|
645
|
+
const entries = (0, fs_1.readdirSync)(dir, { withFileTypes: true });
|
|
646
|
+
for (const entry of entries) {
|
|
647
|
+
if (entry.name.startsWith('.') && entry.name !== '.')
|
|
648
|
+
continue;
|
|
649
|
+
const fullPath = (0, path_1.join)(dir, entry.name);
|
|
650
|
+
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
651
|
+
if (entry.isDirectory()) {
|
|
652
|
+
results.push(`${relPath}/`);
|
|
653
|
+
walk(fullPath, currentDepth + 1, relPath);
|
|
654
|
+
}
|
|
655
|
+
else {
|
|
656
|
+
results.push(relPath);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
catch {
|
|
661
|
+
// skip unreadable directories
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
walk(resolved, 1, '');
|
|
665
|
+
return { success: true, output: results.join('\n') };
|
|
666
|
+
}
|
|
667
|
+
async function execCommand_(command, cwd, timeout) {
|
|
668
|
+
return new Promise((resolve) => {
|
|
669
|
+
const workdir = cwd ? safePath(cwd) : process.cwd();
|
|
670
|
+
const timeoutMs = timeout ?? 30000;
|
|
671
|
+
(0, child_process_1.execFile)('sh', ['-c', command], {
|
|
672
|
+
cwd: workdir,
|
|
673
|
+
timeout: timeoutMs,
|
|
674
|
+
maxBuffer: 1024 * 1024,
|
|
675
|
+
}, (error, stdout, stderr) => {
|
|
676
|
+
const output = stdout.toString().trim();
|
|
677
|
+
const errOutput = stderr.toString().trim();
|
|
678
|
+
if (error) {
|
|
679
|
+
resolve({
|
|
680
|
+
success: false,
|
|
681
|
+
output: output || errOutput,
|
|
682
|
+
error: error.message || `Command exited with code ${error.code}`,
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
resolve({
|
|
687
|
+
success: true,
|
|
688
|
+
output: output || '(no output)',
|
|
689
|
+
error: errOutput || undefined,
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
async function editFile_(path, old_string, new_string, replace_all) {
|
|
696
|
+
try {
|
|
697
|
+
const resolved = safePath(path);
|
|
698
|
+
if (!(0, fs_1.existsSync)(resolved)) {
|
|
699
|
+
return { success: false, output: '', error: `File not found: ${path}` };
|
|
700
|
+
}
|
|
701
|
+
if ((0, fs_1.statSync)(resolved).isDirectory()) {
|
|
702
|
+
return { success: false, output: '', error: `Path is a directory, not a file: ${path}` };
|
|
703
|
+
}
|
|
704
|
+
const content = (0, fs_1.readFileSync)(resolved, 'utf-8');
|
|
705
|
+
// Check if old_string exists
|
|
706
|
+
const count = (content.match(new RegExp(escapeRegExp(old_string), 'g')) || []).length;
|
|
707
|
+
if (count === 0) {
|
|
708
|
+
return { success: false, output: '', error: `old_string not found in file: ${old_string.slice(0, 100)}...` };
|
|
709
|
+
}
|
|
710
|
+
// If not replace_all, require unique match
|
|
711
|
+
if (!replace_all && count > 1) {
|
|
712
|
+
return {
|
|
713
|
+
success: false,
|
|
714
|
+
output: '',
|
|
715
|
+
error: `old_string found ${count} times in file. Use replace_all=true to replace all occurrences, or provide a more specific string that matches exactly once.`,
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
// Perform replacement
|
|
719
|
+
let newContent;
|
|
720
|
+
if (replace_all) {
|
|
721
|
+
newContent = content.split(old_string).join(new_string);
|
|
722
|
+
}
|
|
723
|
+
else {
|
|
724
|
+
// Replace first occurrence only
|
|
725
|
+
const idx = content.indexOf(old_string);
|
|
726
|
+
newContent = content.slice(0, idx) + new_string + content.slice(idx + old_string.length);
|
|
727
|
+
}
|
|
728
|
+
(0, fs_1.writeFileSync)(resolved, newContent, 'utf-8');
|
|
729
|
+
return {
|
|
730
|
+
success: true,
|
|
731
|
+
output: `Replaced ${count} occurrence(s) of old_string with new_string in ${path}`,
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
catch (err) {
|
|
735
|
+
return { success: false, output: '', error: String(err.message) };
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
/** Escape special regex characters for literal matching */
|
|
739
|
+
function escapeRegExp(str) {
|
|
740
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
741
|
+
}
|
|
742
|
+
// ============================================================================
|
|
743
|
+
// Glob/Grep 工具实现
|
|
744
|
+
// ============================================================================
|
|
745
|
+
/**
|
|
746
|
+
* Glob 模式匹配 - 简化版实现
|
|
747
|
+
* 支持: **(递归目录)、*(任意字符)、?(单个字符)
|
|
748
|
+
*/
|
|
749
|
+
async function glob_(pattern, basePath) {
|
|
750
|
+
try {
|
|
751
|
+
const base = basePath ? safePath(basePath) : process.cwd();
|
|
752
|
+
if (!(0, fs_1.existsSync)(base)) {
|
|
753
|
+
return { success: false, output: '', error: `Path not found: ${basePath}` };
|
|
754
|
+
}
|
|
755
|
+
if (!(0, fs_1.statSync)(base).isDirectory()) {
|
|
756
|
+
return { success: false, output: '', error: `Path is not a directory: ${basePath}` };
|
|
757
|
+
}
|
|
758
|
+
const results = [];
|
|
759
|
+
// Convert glob pattern to regex
|
|
760
|
+
function globToRegex(pat) {
|
|
761
|
+
// Use placeholders to avoid interference between replacements
|
|
762
|
+
let regex = pat;
|
|
763
|
+
// **/ at start - matches optional path (including empty)
|
|
764
|
+
regex = regex.replace(/^\*\*\//, '<<STARSTAR_SLASH_START>>');
|
|
765
|
+
// **/ in middle - matches any number of path segments
|
|
766
|
+
regex = regex.replace(/\*\*\//g, '<<STARSTAR_SLASH>>');
|
|
767
|
+
// standalone ** - matches anything
|
|
768
|
+
regex = regex.replace(/\*\*/g, '<<STARSTAR>>');
|
|
769
|
+
// escape dots
|
|
770
|
+
regex = regex.replace(/\./g, '\\.');
|
|
771
|
+
// * matches anything except /
|
|
772
|
+
regex = regex.replace(/\*/g, '[^/]*');
|
|
773
|
+
// ? matches single char except /
|
|
774
|
+
regex = regex.replace(/\?/g, '[^/]');
|
|
775
|
+
// Now restore ** placeholders
|
|
776
|
+
regex = regex.replace(/<<STARSTAR_SLASH_START>>/g, '(.*\\/)?');
|
|
777
|
+
regex = regex.replace(/<<STARSTAR_SLASH>>/g, '([^/]+\\/)*');
|
|
778
|
+
regex = regex.replace(/<<STARSTAR>>/g, '.*');
|
|
779
|
+
return new RegExp(`^${regex}$`);
|
|
780
|
+
}
|
|
781
|
+
const regex = globToRegex(pattern);
|
|
782
|
+
// Recursive walk
|
|
783
|
+
function walk(dir, prefix) {
|
|
784
|
+
try {
|
|
785
|
+
const entries = (0, fs_1.readdirSync)(dir, { withFileTypes: true });
|
|
786
|
+
for (const entry of entries) {
|
|
787
|
+
if (entry.name.startsWith('.'))
|
|
788
|
+
continue;
|
|
789
|
+
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
790
|
+
if (entry.isDirectory()) {
|
|
791
|
+
walk((0, path_1.join)(dir, entry.name), relPath);
|
|
792
|
+
}
|
|
793
|
+
else {
|
|
794
|
+
if (regex.test(relPath)) {
|
|
795
|
+
results.push(relPath);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
catch {
|
|
801
|
+
// skip unreadable directories
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
walk(base, '');
|
|
805
|
+
if (results.length === 0) {
|
|
806
|
+
return { success: true, output: 'No files found matching pattern' };
|
|
807
|
+
}
|
|
808
|
+
return { success: true, output: results.sort().join('\n') };
|
|
809
|
+
}
|
|
810
|
+
catch (err) {
|
|
811
|
+
return { success: false, output: '', error: String(err.message) };
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Grep 搜索 - 在文件中搜索正则表达式
|
|
816
|
+
*/
|
|
817
|
+
async function grep_(pattern, basePath, globPattern, contextLines) {
|
|
818
|
+
try {
|
|
819
|
+
const base = basePath ? safePath(basePath) : process.cwd();
|
|
820
|
+
if (!(0, fs_1.existsSync)(base)) {
|
|
821
|
+
return { success: false, output: '', error: `Path not found: ${basePath}` };
|
|
822
|
+
}
|
|
823
|
+
const regex = new RegExp(pattern, 'g');
|
|
824
|
+
const context = contextLines ?? 0;
|
|
825
|
+
const results = [];
|
|
826
|
+
const maxResults = 100;
|
|
827
|
+
// Get list of files to search
|
|
828
|
+
const files = [];
|
|
829
|
+
function collectFiles(dir) {
|
|
830
|
+
try {
|
|
831
|
+
const entries = (0, fs_1.readdirSync)(dir, { withFileTypes: true });
|
|
832
|
+
for (const entry of entries) {
|
|
833
|
+
if (entry.name.startsWith('.'))
|
|
834
|
+
continue;
|
|
835
|
+
const fullPath = (0, path_1.join)(dir, entry.name);
|
|
836
|
+
if (entry.isDirectory()) {
|
|
837
|
+
collectFiles(fullPath);
|
|
838
|
+
}
|
|
839
|
+
else {
|
|
840
|
+
// Check glob filter if provided
|
|
841
|
+
if (globPattern) {
|
|
842
|
+
const ext = (0, path_1.extname)(entry.name);
|
|
843
|
+
if (!matchGlobSimple(entry.name, globPattern))
|
|
844
|
+
continue;
|
|
845
|
+
}
|
|
846
|
+
files.push(fullPath);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
catch {
|
|
851
|
+
// skip unreadable
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
function matchGlobSimple(name, pat) {
|
|
855
|
+
const regex = pat.replace(/\*/g, '.*').replace(/\?/g, '.').replace(/\./g, '\\.');
|
|
856
|
+
return new RegExp(`^${regex}$`).test(name);
|
|
857
|
+
}
|
|
858
|
+
if ((0, fs_1.statSync)(base).isDirectory()) {
|
|
859
|
+
collectFiles(base);
|
|
860
|
+
}
|
|
861
|
+
else {
|
|
862
|
+
files.push(base);
|
|
863
|
+
}
|
|
864
|
+
// Search each file
|
|
865
|
+
for (const file of files) {
|
|
866
|
+
if (results.length >= maxResults)
|
|
867
|
+
break;
|
|
868
|
+
try {
|
|
869
|
+
const rl = (0, readline_1.createInterface)({
|
|
870
|
+
input: (0, fs_1.createReadStream)(file, { encoding: 'utf-8' }),
|
|
871
|
+
crlfDelay: Infinity,
|
|
872
|
+
});
|
|
873
|
+
const lines = [];
|
|
874
|
+
const relPath = (0, path_1.relative)(base, file);
|
|
875
|
+
rl.on('line', (line) => {
|
|
876
|
+
lines.push(line);
|
|
877
|
+
});
|
|
878
|
+
await new Promise((resolve) => {
|
|
879
|
+
rl.on('close', resolve);
|
|
880
|
+
});
|
|
881
|
+
// Search for matches
|
|
882
|
+
for (let i = 0; i < lines.length && results.length < maxResults; i++) {
|
|
883
|
+
if (regex.test(lines[i])) {
|
|
884
|
+
// Format: file:line:content
|
|
885
|
+
const start = Math.max(0, i - context);
|
|
886
|
+
const end = Math.min(lines.length - 1, i + context);
|
|
887
|
+
if (context > 0) {
|
|
888
|
+
results.push(`${relPath}:${i + 1}:`);
|
|
889
|
+
for (let j = start; j <= end; j++) {
|
|
890
|
+
const prefix = j === i ? '>' : ' ';
|
|
891
|
+
results.push(` ${prefix}${j + 1}: ${lines[j]}`);
|
|
892
|
+
}
|
|
893
|
+
results.push('');
|
|
894
|
+
}
|
|
895
|
+
else {
|
|
896
|
+
results.push(`${relPath}:${i + 1}: ${lines[i]}`);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
catch {
|
|
902
|
+
// skip unreadable files
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
if (results.length === 0) {
|
|
906
|
+
return { success: true, output: 'No matches found' };
|
|
907
|
+
}
|
|
908
|
+
return { success: true, output: results.slice(0, maxResults).join('\n') };
|
|
909
|
+
}
|
|
910
|
+
catch (err) {
|
|
911
|
+
return { success: false, output: '', error: String(err.message) };
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
// ============================================================================
|
|
915
|
+
// 统一执行入口
|
|
916
|
+
// ============================================================================
|
|
917
|
+
/**
|
|
918
|
+
* 执行一个工具调用,返回结构化结果字符串
|
|
919
|
+
*/
|
|
920
|
+
async function executeTool(name, args) {
|
|
921
|
+
const tool = exports.TOOLS.find(t => t.name === name);
|
|
922
|
+
if (!tool) {
|
|
923
|
+
return JSON.stringify({
|
|
924
|
+
success: false,
|
|
925
|
+
error: `Unknown tool: ${name}. Available tools: ${exports.TOOLS.map(t => t.name).join(', ')}`,
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
const context = {
|
|
929
|
+
cwd: process.cwd(),
|
|
930
|
+
config: {
|
|
931
|
+
name: 'openhorse',
|
|
932
|
+
mode: 'development',
|
|
933
|
+
},
|
|
934
|
+
};
|
|
935
|
+
const result = await tool.execute(args, context);
|
|
936
|
+
if (!result.success) {
|
|
937
|
+
return JSON.stringify({
|
|
938
|
+
success: false,
|
|
939
|
+
error: result.error,
|
|
940
|
+
output: result.output,
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
return JSON.stringify({
|
|
944
|
+
success: true,
|
|
945
|
+
output: result.output,
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* 获取可用工具名称列表
|
|
950
|
+
*/
|
|
951
|
+
function getToolNames() {
|
|
952
|
+
return exports.TOOLS.map(t => t.name).join(', ');
|
|
953
|
+
}
|
|
954
|
+
// Re-export bash_security module
|
|
955
|
+
var bash_security_2 = require("./bash_security");
|
|
956
|
+
Object.defineProperty(exports, "READ_ONLY_COMMANDS", { enumerable: true, get: function () { return bash_security_2.READ_ONLY_COMMANDS; } });
|
|
957
|
+
Object.defineProperty(exports, "DANGEROUS_PATTERNS", { enumerable: true, get: function () { return bash_security_2.DANGEROUS_PATTERNS; } });
|
|
958
|
+
Object.defineProperty(exports, "POTENTIALLY_DESTRUCTIVE_PATTERNS", { enumerable: true, get: function () { return bash_security_2.POTENTIALLY_DESTRUCTIVE_PATTERNS; } });
|
|
959
|
+
Object.defineProperty(exports, "isReadOnlyCommand", { enumerable: true, get: function () { return bash_security_2.isReadOnlyCommand; } });
|
|
960
|
+
Object.defineProperty(exports, "checkDangerousCommand", { enumerable: true, get: function () { return bash_security_2.checkDangerousCommand; } });
|
|
961
|
+
Object.defineProperty(exports, "isPotentiallyDestructive", { enumerable: true, get: function () { return bash_security_2.isPotentiallyDestructive; } });
|
|
962
|
+
Object.defineProperty(exports, "assessCommandSecurity", { enumerable: true, get: function () { return bash_security_2.assessCommandSecurity; } });
|
|
963
|
+
Object.defineProperty(exports, "wrapForSandbox", { enumerable: true, get: function () { return bash_security_2.wrapForSandbox; } });
|
|
964
|
+
Object.defineProperty(exports, "DEFAULT_SANDBOX_OPTIONS", { enumerable: true, get: function () { return bash_security_2.DEFAULT_SANDBOX_OPTIONS; } });
|
|
965
|
+
//# sourceMappingURL=index.js.map
|