bone-agent 1.3.0

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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -0
  3. package/bin/npm-wrapper.js +235 -0
  4. package/bin/rg +0 -0
  5. package/bin/rg.exe +0 -0
  6. package/config.yaml.example +133 -0
  7. package/package.json +53 -0
  8. package/requirements.txt +9 -0
  9. package/src/__init__.py +11 -0
  10. package/src/core/__init__.py +1 -0
  11. package/src/core/agentic.py +1054 -0
  12. package/src/core/chat_manager.py +1552 -0
  13. package/src/core/config_manager.py +247 -0
  14. package/src/core/cron.py +527 -0
  15. package/src/core/cron_allowlist.py +118 -0
  16. package/src/core/memory.py +232 -0
  17. package/src/core/retry.py +71 -0
  18. package/src/core/sub_agent.py +326 -0
  19. package/src/core/tool_approval.py +220 -0
  20. package/src/core/tool_feedback.py +778 -0
  21. package/src/exceptions.py +79 -0
  22. package/src/llm/__init__.py +1 -0
  23. package/src/llm/client.py +171 -0
  24. package/src/llm/config.py +466 -0
  25. package/src/llm/prompts.py +735 -0
  26. package/src/llm/providers.py +417 -0
  27. package/src/llm/streaming.py +163 -0
  28. package/src/llm/token_tracker.py +368 -0
  29. package/src/tools/__init__.py +212 -0
  30. package/src/tools/constants.py +59 -0
  31. package/src/tools/create_file.py +136 -0
  32. package/src/tools/directory.py +389 -0
  33. package/src/tools/edit.py +543 -0
  34. package/src/tools/file_reader.py +322 -0
  35. package/src/tools/helpers/__init__.py +105 -0
  36. package/src/tools/helpers/base.py +550 -0
  37. package/src/tools/helpers/converters.py +44 -0
  38. package/src/tools/helpers/file_helpers.py +189 -0
  39. package/src/tools/helpers/formatters.py +411 -0
  40. package/src/tools/helpers/loader.py +231 -0
  41. package/src/tools/helpers/parallel_executor.py +231 -0
  42. package/src/tools/helpers/path_resolver.py +226 -0
  43. package/src/tools/helpers/plugin_manifest.py +156 -0
  44. package/src/tools/obsidian.py +96 -0
  45. package/src/tools/review_sub_agent.py +189 -0
  46. package/src/tools/rg_search.py +393 -0
  47. package/src/tools/search_plugins.py +109 -0
  48. package/src/tools/select_option.py +593 -0
  49. package/src/tools/shell.py +302 -0
  50. package/src/tools/sub_agent.py +139 -0
  51. package/src/tools/task_list.py +269 -0
  52. package/src/tools/web_search.py +61 -0
  53. package/src/ui/__init__.py +1 -0
  54. package/src/ui/banner.py +87 -0
  55. package/src/ui/commands.py +2694 -0
  56. package/src/ui/displays.py +213 -0
  57. package/src/ui/loader.py +284 -0
  58. package/src/ui/main.py +646 -0
  59. package/src/ui/prompt_utils.py +113 -0
  60. package/src/ui/setting_selector.py +590 -0
  61. package/src/ui/setup_wizard.py +294 -0
  62. package/src/ui/sub_agent_panel.py +234 -0
  63. package/src/ui/tool_confirmation.py +215 -0
  64. package/src/utils/__init__.py +1 -0
  65. package/src/utils/citation_parser.py +199 -0
  66. package/src/utils/editor.py +158 -0
  67. package/src/utils/gitignore_filter.py +149 -0
  68. package/src/utils/logger.py +254 -0
  69. package/src/utils/paths.py +30 -0
  70. package/src/utils/result_parsers.py +108 -0
  71. package/src/utils/safe_commands.py +243 -0
  72. package/src/utils/settings.py +174 -0
  73. package/src/utils/validation.py +191 -0
  74. package/src/utils/web_search.py +173 -0
@@ -0,0 +1,113 @@
1
+ """Shared prompt utilities for bone-agent CLI."""
2
+
3
+ from prompt_toolkit import PromptSession
4
+ from prompt_toolkit.key_binding import KeyBindings
5
+ from prompt_toolkit.styles import Style
6
+ from prompt_toolkit.formatted_text import HTML
7
+ from llm.config import get_provider_config, APPROVE_MODE_LABELS, STATUS_BAR_SETTINGS
8
+
9
+
10
+ def get_bottom_toolbar_text(chat_manager):
11
+ """Return bottom toolbar text with model, approval mode, and token count.
12
+
13
+ This is extracted from main.py for reuse in confirmation prompts.
14
+
15
+ Args:
16
+ chat_manager: ChatManager instance for state access
17
+
18
+ Returns:
19
+ HTML formatted toolbar text
20
+ """
21
+ provider_name = chat_manager.client.provider
22
+ model = get_provider_config(provider_name).get("model", "Unknown")
23
+
24
+ # Get token counts
25
+ tokens_curr = chat_manager.token_tracker.current_context_tokens
26
+ tokens_in = chat_manager.token_tracker.total_prompt_tokens
27
+ tokens_out = chat_manager.token_tracker.total_completion_tokens
28
+ tokens_total = chat_manager.token_tracker.total_tokens
29
+
30
+ # Calculate cost — prefer upstream-reported actual cost (e.g. OpenRouter)
31
+ # over locally estimated cost from token counts × static rates
32
+ total_cost = chat_manager.token_tracker.get_display_cost(model)
33
+
34
+ # Format model name (take last part if path)
35
+ if "\\" in model or "/" in model:
36
+ model_display = model.split("\\")[-1].split("/")[-1]
37
+ else:
38
+ model_display = model
39
+
40
+ # Determine mode label and color
41
+ mode_label = "Approval"
42
+ val = APPROVE_MODE_LABELS.get(chat_manager.approve_mode, chat_manager.approve_mode.upper())
43
+ colors = {"safe": "#6B8E23", "accept_edits": "#DAA520", "danger": "#CD5C5C"}
44
+ mode_val_colored = f'<style fg="{colors.get(chat_manager.approve_mode, "white")}">{val}</style>'
45
+
46
+ # Build toolbar string based on configuration
47
+ # Model and mode are always shown
48
+ parts = [f'<style fg="#606060">Model: {model_display or provider_name} - {mode_label}: </style>{mode_val_colored}']
49
+
50
+ # Conditionally add token counts
51
+ if STATUS_BAR_SETTINGS.get("show_curr_tokens", True):
52
+ parts.append(f'<style fg="#606060"> | </style><style fg="#808080">curr</style><style fg="#606060">: {tokens_curr:,}</style>')
53
+ if STATUS_BAR_SETTINGS.get("show_in_tokens", True):
54
+ parts.append(f'<style fg="#606060"> | </style><style fg="#808080">in</style><style fg="#606060">: {tokens_in:,}</style>')
55
+ if STATUS_BAR_SETTINGS.get("show_out_tokens", True):
56
+ parts.append(f'<style fg="#606060"> | </style><style fg="#808080">out</style><style fg="#606060">: {tokens_out:,}</style>')
57
+ if STATUS_BAR_SETTINGS.get("show_total_tokens", True):
58
+ parts.append(f'<style fg="#606060"> | </style><style fg="#808080">total</style><style fg="#606060">: {tokens_total:,}</style>')
59
+
60
+ # Conditionally add cost
61
+ if STATUS_BAR_SETTINGS.get("show_cost", True):
62
+ parts.append(f'<style fg="#606060"> | </style><style fg="#808080">cost</style><style fg="#606060">: ${total_cost:.4f}</style>')
63
+
64
+ return HTML('\n' + ''.join(parts))
65
+
66
+
67
+ TOOLBAR_STYLE = Style.from_dict({
68
+ "bottom-toolbar": "bg:default fg:#FFFFFF noreverse",
69
+ "bottom-toolbar.text": "bg:default fg:#FFFFFF noreverse",
70
+ })
71
+
72
+
73
+ def setup_common_bindings(chat_manager):
74
+ """Create KeyBindings with shared logic (e.g., Shift+Tab for mode cycling)."""
75
+ bindings = KeyBindings()
76
+
77
+ @bindings.add('s-tab')
78
+ def toggle_approve_mode(event):
79
+ """Toggle between modes using Shift+Tab (blocked during thinking)."""
80
+ # Import here to avoid circular imports and get current state
81
+ import importlib
82
+ main_module = importlib.import_module('ui.main')
83
+ if main_module.INPUT_BLOCKED.get('blocked', False):
84
+ return
85
+ chat_manager.cycle_approve_mode()
86
+ event.app.invalidate()
87
+
88
+ return bindings
89
+
90
+
91
+ def create_confirmation_prompt_session(chat_manager, message_func):
92
+ """Create a PromptSession for confirmation prompts with key bindings and toolbar.
93
+
94
+ This provides:
95
+ - Shift+Tab to toggle approval mode
96
+ - Bottom toolbar showing model, approval mode, and token counts
97
+ - Dynamic prompt message that updates when mode changes
98
+
99
+ Args:
100
+ chat_manager: ChatManager instance for state access
101
+ message_func: Function that returns the prompt message HTML (called on each redraw)
102
+
103
+ Returns:
104
+ PromptSession configured with bindings and toolbar
105
+ """
106
+ bindings = setup_common_bindings(chat_manager)
107
+
108
+ return PromptSession(
109
+ key_bindings=bindings,
110
+ style=TOOLBAR_STYLE,
111
+ bottom_toolbar=lambda: get_bottom_toolbar_text(chat_manager),
112
+ message=message_func
113
+ )