kollabor 0.4.9__py3-none-any.whl → 0.4.15__py3-none-any.whl
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.
- agents/__init__.py +2 -0
- agents/coder/__init__.py +0 -0
- agents/coder/agent.json +4 -0
- agents/coder/api-integration.md +2150 -0
- agents/coder/cli-pretty.md +765 -0
- agents/coder/code-review.md +1092 -0
- agents/coder/database-design.md +1525 -0
- agents/coder/debugging.md +1102 -0
- agents/coder/dependency-management.md +1397 -0
- agents/coder/git-workflow.md +1099 -0
- agents/coder/refactoring.md +1454 -0
- agents/coder/security-hardening.md +1732 -0
- agents/coder/system_prompt.md +1448 -0
- agents/coder/tdd.md +1367 -0
- agents/creative-writer/__init__.py +0 -0
- agents/creative-writer/agent.json +4 -0
- agents/creative-writer/character-development.md +1852 -0
- agents/creative-writer/dialogue-craft.md +1122 -0
- agents/creative-writer/plot-structure.md +1073 -0
- agents/creative-writer/revision-editing.md +1484 -0
- agents/creative-writer/system_prompt.md +690 -0
- agents/creative-writer/worldbuilding.md +2049 -0
- agents/data-analyst/__init__.py +30 -0
- agents/data-analyst/agent.json +4 -0
- agents/data-analyst/data-visualization.md +992 -0
- agents/data-analyst/exploratory-data-analysis.md +1110 -0
- agents/data-analyst/pandas-data-manipulation.md +1081 -0
- agents/data-analyst/sql-query-optimization.md +881 -0
- agents/data-analyst/statistical-analysis.md +1118 -0
- agents/data-analyst/system_prompt.md +928 -0
- agents/default/__init__.py +0 -0
- agents/default/agent.json +4 -0
- agents/default/dead-code.md +794 -0
- agents/default/explore-agent-system.md +585 -0
- agents/default/system_prompt.md +1448 -0
- agents/kollabor/__init__.py +0 -0
- agents/kollabor/analyze-plugin-lifecycle.md +175 -0
- agents/kollabor/analyze-terminal-rendering.md +388 -0
- agents/kollabor/code-review.md +1092 -0
- agents/kollabor/debug-mcp-integration.md +521 -0
- agents/kollabor/debug-plugin-hooks.md +547 -0
- agents/kollabor/debugging.md +1102 -0
- agents/kollabor/dependency-management.md +1397 -0
- agents/kollabor/git-workflow.md +1099 -0
- agents/kollabor/inspect-llm-conversation.md +148 -0
- agents/kollabor/monitor-event-bus.md +558 -0
- agents/kollabor/profile-performance.md +576 -0
- agents/kollabor/refactoring.md +1454 -0
- agents/kollabor/system_prompt copy.md +1448 -0
- agents/kollabor/system_prompt.md +757 -0
- agents/kollabor/trace-command-execution.md +178 -0
- agents/kollabor/validate-config.md +879 -0
- agents/research/__init__.py +0 -0
- agents/research/agent.json +4 -0
- agents/research/architecture-mapping.md +1099 -0
- agents/research/codebase-analysis.md +1077 -0
- agents/research/dependency-audit.md +1027 -0
- agents/research/performance-profiling.md +1047 -0
- agents/research/security-review.md +1359 -0
- agents/research/system_prompt.md +492 -0
- agents/technical-writer/__init__.py +0 -0
- agents/technical-writer/agent.json +4 -0
- agents/technical-writer/api-documentation.md +2328 -0
- agents/technical-writer/changelog-management.md +1181 -0
- agents/technical-writer/readme-writing.md +1360 -0
- agents/technical-writer/style-guide.md +1410 -0
- agents/technical-writer/system_prompt.md +653 -0
- agents/technical-writer/tutorial-creation.md +1448 -0
- core/__init__.py +0 -2
- core/application.py +343 -88
- core/cli.py +229 -10
- core/commands/menu_renderer.py +463 -59
- core/commands/registry.py +14 -9
- core/commands/system_commands.py +2461 -14
- core/config/loader.py +151 -37
- core/config/service.py +18 -6
- core/events/bus.py +29 -9
- core/events/executor.py +205 -75
- core/events/models.py +27 -8
- core/fullscreen/command_integration.py +20 -24
- core/fullscreen/components/__init__.py +10 -1
- core/fullscreen/components/matrix_components.py +1 -2
- core/fullscreen/components/space_shooter_components.py +654 -0
- core/fullscreen/plugin.py +5 -0
- core/fullscreen/renderer.py +52 -13
- core/fullscreen/session.py +52 -15
- core/io/__init__.py +29 -5
- core/io/buffer_manager.py +6 -1
- core/io/config_status_view.py +7 -29
- core/io/core_status_views.py +267 -347
- core/io/input/__init__.py +25 -0
- core/io/input/command_mode_handler.py +711 -0
- core/io/input/display_controller.py +128 -0
- core/io/input/hook_registrar.py +286 -0
- core/io/input/input_loop_manager.py +421 -0
- core/io/input/key_press_handler.py +502 -0
- core/io/input/modal_controller.py +1011 -0
- core/io/input/paste_processor.py +339 -0
- core/io/input/status_modal_renderer.py +184 -0
- core/io/input_errors.py +5 -1
- core/io/input_handler.py +211 -2452
- core/io/key_parser.py +7 -0
- core/io/layout.py +15 -3
- core/io/message_coordinator.py +111 -2
- core/io/message_renderer.py +129 -4
- core/io/status_renderer.py +147 -607
- core/io/terminal_renderer.py +97 -51
- core/io/terminal_state.py +21 -4
- core/io/visual_effects.py +816 -165
- core/llm/agent_manager.py +1063 -0
- core/llm/api_adapters/__init__.py +44 -0
- core/llm/api_adapters/anthropic_adapter.py +432 -0
- core/llm/api_adapters/base.py +241 -0
- core/llm/api_adapters/openai_adapter.py +326 -0
- core/llm/api_communication_service.py +167 -113
- core/llm/conversation_logger.py +322 -16
- core/llm/conversation_manager.py +556 -30
- core/llm/file_operations_executor.py +84 -32
- core/llm/llm_service.py +934 -103
- core/llm/mcp_integration.py +541 -57
- core/llm/message_display_service.py +135 -18
- core/llm/plugin_sdk.py +1 -2
- core/llm/profile_manager.py +1183 -0
- core/llm/response_parser.py +274 -56
- core/llm/response_processor.py +16 -3
- core/llm/tool_executor.py +6 -1
- core/logging/__init__.py +2 -0
- core/logging/setup.py +34 -6
- core/models/resume.py +54 -0
- core/plugins/__init__.py +4 -2
- core/plugins/base.py +127 -0
- core/plugins/collector.py +23 -161
- core/plugins/discovery.py +37 -3
- core/plugins/factory.py +6 -12
- core/plugins/registry.py +5 -17
- core/ui/config_widgets.py +128 -28
- core/ui/live_modal_renderer.py +2 -1
- core/ui/modal_actions.py +5 -0
- core/ui/modal_overlay_renderer.py +0 -60
- core/ui/modal_renderer.py +268 -7
- core/ui/modal_state_manager.py +29 -4
- core/ui/widgets/base_widget.py +7 -0
- core/updates/__init__.py +10 -0
- core/updates/version_check_service.py +348 -0
- core/updates/version_comparator.py +103 -0
- core/utils/config_utils.py +685 -526
- core/utils/plugin_utils.py +1 -1
- core/utils/session_naming.py +111 -0
- fonts/LICENSE +21 -0
- fonts/README.md +46 -0
- fonts/SymbolsNerdFont-Regular.ttf +0 -0
- fonts/SymbolsNerdFontMono-Regular.ttf +0 -0
- fonts/__init__.py +44 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/METADATA +54 -4
- kollabor-0.4.15.dist-info/RECORD +228 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/top_level.txt +2 -0
- plugins/agent_orchestrator/__init__.py +39 -0
- plugins/agent_orchestrator/activity_monitor.py +181 -0
- plugins/agent_orchestrator/file_attacher.py +77 -0
- plugins/agent_orchestrator/message_injector.py +135 -0
- plugins/agent_orchestrator/models.py +48 -0
- plugins/agent_orchestrator/orchestrator.py +403 -0
- plugins/agent_orchestrator/plugin.py +976 -0
- plugins/agent_orchestrator/xml_parser.py +191 -0
- plugins/agent_orchestrator_plugin.py +9 -0
- plugins/enhanced_input/box_styles.py +1 -0
- plugins/enhanced_input/color_engine.py +19 -4
- plugins/enhanced_input/config.py +2 -2
- plugins/enhanced_input_plugin.py +61 -11
- plugins/fullscreen/__init__.py +6 -2
- plugins/fullscreen/example_plugin.py +1035 -222
- plugins/fullscreen/setup_wizard_plugin.py +592 -0
- plugins/fullscreen/space_shooter_plugin.py +131 -0
- plugins/hook_monitoring_plugin.py +436 -78
- plugins/query_enhancer_plugin.py +66 -30
- plugins/resume_conversation_plugin.py +1494 -0
- plugins/save_conversation_plugin.py +98 -32
- plugins/system_commands_plugin.py +70 -56
- plugins/tmux_plugin.py +154 -78
- plugins/workflow_enforcement_plugin.py +94 -92
- system_prompt/default.md +952 -886
- core/io/input_mode_manager.py +0 -402
- core/io/modal_interaction_handler.py +0 -315
- core/io/raw_input_processor.py +0 -946
- core/storage/__init__.py +0 -5
- core/storage/state_manager.py +0 -84
- core/ui/widget_integration.py +0 -222
- core/utils/key_reader.py +0 -171
- kollabor-0.4.9.dist-info/RECORD +0 -128
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/WHEEL +0 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/entry_points.txt +0 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -26,6 +26,9 @@ from typing import Any, Dict, List, Optional, Tuple
|
|
|
26
26
|
|
|
27
27
|
logger = logging.getLogger(__name__)
|
|
28
28
|
|
|
29
|
+
# Global kollabor config directory - allowed for read operations
|
|
30
|
+
KOLLABOR_CONFIG_DIR = Path.home() / ".kollabor-cli"
|
|
31
|
+
|
|
29
32
|
|
|
30
33
|
class FileOperationsExecutor:
|
|
31
34
|
"""Execute file operations with comprehensive safety features.
|
|
@@ -88,35 +91,55 @@ class FileOperationsExecutor:
|
|
|
88
91
|
return self.config.get(key, default)
|
|
89
92
|
return default
|
|
90
93
|
|
|
91
|
-
def validate_file_path(self, filepath: str) -> Tuple[bool, str]:
|
|
94
|
+
def validate_file_path(self, filepath: str, allow_kollabor_config: bool = False) -> Tuple[bool, str, str]:
|
|
92
95
|
"""Validate file path for security and correctness.
|
|
93
96
|
|
|
94
97
|
Args:
|
|
95
98
|
filepath: File path to validate
|
|
99
|
+
allow_kollabor_config: If True, allow absolute paths within ~/.kollabor-cli/
|
|
96
100
|
|
|
97
101
|
Returns:
|
|
98
|
-
(is_valid, error_message)
|
|
102
|
+
(is_valid, error_message, normalized_path)
|
|
103
|
+
normalized_path will be the filepath with tilde expanded if applicable
|
|
99
104
|
"""
|
|
100
105
|
if not filepath:
|
|
101
|
-
return False, "Empty file path"
|
|
106
|
+
return False, "Empty file path", filepath
|
|
102
107
|
|
|
103
108
|
# Security: No path traversal
|
|
104
109
|
if ".." in filepath:
|
|
105
|
-
return False, f"Path traversal detected: {filepath}"
|
|
110
|
+
return False, f"Path traversal detected: {filepath}", filepath
|
|
111
|
+
|
|
112
|
+
# Expand tilde if present
|
|
113
|
+
normalized_path = filepath
|
|
114
|
+
if filepath.startswith("~"):
|
|
115
|
+
normalized_path = str(Path(filepath).expanduser())
|
|
106
116
|
|
|
107
117
|
# Security: No absolute paths (relative paths only)
|
|
108
|
-
|
|
109
|
-
|
|
118
|
+
# Exception: Allow paths within ~/.kollabor-cli/ for read operations
|
|
119
|
+
if normalized_path.startswith("/") or (len(normalized_path) > 1 and normalized_path[1] == ":"):
|
|
120
|
+
if allow_kollabor_config:
|
|
121
|
+
# Check if path is within kollabor config directory
|
|
122
|
+
try:
|
|
123
|
+
resolved = Path(normalized_path).resolve()
|
|
124
|
+
if resolved.is_relative_to(KOLLABOR_CONFIG_DIR):
|
|
125
|
+
# Path is within kollabor config - allow it
|
|
126
|
+
pass
|
|
127
|
+
else:
|
|
128
|
+
return False, f"Absolute paths only allowed within {KOLLABOR_CONFIG_DIR}: {filepath}", normalized_path
|
|
129
|
+
except (ValueError, OSError):
|
|
130
|
+
return False, f"Invalid absolute path: {filepath}", normalized_path
|
|
131
|
+
else:
|
|
132
|
+
return False, f"Absolute paths not allowed: {filepath}", normalized_path
|
|
110
133
|
|
|
111
134
|
# Practical: Path length limit
|
|
112
|
-
if len(
|
|
113
|
-
return False, f"Path too long: {len(
|
|
135
|
+
if len(normalized_path) > 255:
|
|
136
|
+
return False, f"Path too long: {len(normalized_path)} chars (max 255)", normalized_path
|
|
114
137
|
|
|
115
138
|
# Security: No null bytes
|
|
116
|
-
if "\x00" in
|
|
117
|
-
return False, "Null byte in file path"
|
|
139
|
+
if "\x00" in normalized_path:
|
|
140
|
+
return False, "Null byte in file path", normalized_path
|
|
118
141
|
|
|
119
|
-
return True, ""
|
|
142
|
+
return True, "", normalized_path
|
|
120
143
|
|
|
121
144
|
def is_protected_path(self, filepath: str) -> bool:
|
|
122
145
|
"""Check if file path is protected from deletion/modification.
|
|
@@ -374,7 +397,8 @@ class FileOperationsExecutor:
|
|
|
374
397
|
"error": "Missing required fields: file, find, replace"
|
|
375
398
|
}
|
|
376
399
|
|
|
377
|
-
|
|
400
|
+
# Allow editing files in ~/.kollabor-cli/ (skill files for global agents)
|
|
401
|
+
is_valid, error, filepath = self.validate_file_path(filepath, allow_kollabor_config=True)
|
|
378
402
|
if not is_valid:
|
|
379
403
|
return {"success": False, "error": error}
|
|
380
404
|
|
|
@@ -489,7 +513,8 @@ class FileOperationsExecutor:
|
|
|
489
513
|
if not filepath:
|
|
490
514
|
return {"success": False, "error": "Missing file path"}
|
|
491
515
|
|
|
492
|
-
|
|
516
|
+
# Allow creating files in ~/.kollabor-cli/ (skill files for global agents)
|
|
517
|
+
is_valid, error, filepath = self.validate_file_path(filepath, allow_kollabor_config=True)
|
|
493
518
|
if not is_valid:
|
|
494
519
|
return {"success": False, "error": error}
|
|
495
520
|
|
|
@@ -562,7 +587,8 @@ class FileOperationsExecutor:
|
|
|
562
587
|
if not filepath:
|
|
563
588
|
return {"success": False, "error": "Missing file path"}
|
|
564
589
|
|
|
565
|
-
|
|
590
|
+
# Allow overwriting files in ~/.kollabor-cli/ (skill files for global agents)
|
|
591
|
+
is_valid, error, filepath = self.validate_file_path(filepath, allow_kollabor_config=True)
|
|
566
592
|
if not is_valid:
|
|
567
593
|
return {"success": False, "error": error}
|
|
568
594
|
|
|
@@ -633,7 +659,7 @@ class FileOperationsExecutor:
|
|
|
633
659
|
if not filepath:
|
|
634
660
|
return {"success": False, "error": "Missing file path"}
|
|
635
661
|
|
|
636
|
-
is_valid, error = self.validate_file_path(filepath)
|
|
662
|
+
is_valid, error, filepath = self.validate_file_path(filepath)
|
|
637
663
|
if not is_valid:
|
|
638
664
|
return {"success": False, "error": error}
|
|
639
665
|
|
|
@@ -687,11 +713,11 @@ class FileOperationsExecutor:
|
|
|
687
713
|
if not from_path or not to_path:
|
|
688
714
|
return {"success": False, "error": "Missing from/to paths"}
|
|
689
715
|
|
|
690
|
-
is_valid, error = self.validate_file_path(from_path)
|
|
716
|
+
is_valid, error, from_path = self.validate_file_path(from_path)
|
|
691
717
|
if not is_valid:
|
|
692
718
|
return {"success": False, "error": f"Source: {error}"}
|
|
693
719
|
|
|
694
|
-
is_valid, error = self.validate_file_path(to_path)
|
|
720
|
+
is_valid, error, to_path = self.validate_file_path(to_path)
|
|
695
721
|
if not is_valid:
|
|
696
722
|
return {"success": False, "error": f"Destination: {error}"}
|
|
697
723
|
|
|
@@ -755,11 +781,11 @@ class FileOperationsExecutor:
|
|
|
755
781
|
if not from_path or not to_path:
|
|
756
782
|
return {"success": False, "error": "Missing from/to paths"}
|
|
757
783
|
|
|
758
|
-
is_valid, error = self.validate_file_path(from_path)
|
|
784
|
+
is_valid, error, from_path = self.validate_file_path(from_path)
|
|
759
785
|
if not is_valid:
|
|
760
786
|
return {"success": False, "error": f"Source: {error}"}
|
|
761
787
|
|
|
762
|
-
is_valid, error = self.validate_file_path(to_path)
|
|
788
|
+
is_valid, error, to_path = self.validate_file_path(to_path)
|
|
763
789
|
if not is_valid:
|
|
764
790
|
return {"success": False, "error": f"Destination: {error}"}
|
|
765
791
|
|
|
@@ -817,11 +843,11 @@ class FileOperationsExecutor:
|
|
|
817
843
|
if not from_path or not to_path:
|
|
818
844
|
return {"success": False, "error": "Missing from/to paths"}
|
|
819
845
|
|
|
820
|
-
is_valid, error = self.validate_file_path(from_path)
|
|
846
|
+
is_valid, error, from_path = self.validate_file_path(from_path)
|
|
821
847
|
if not is_valid:
|
|
822
848
|
return {"success": False, "error": f"Source: {error}"}
|
|
823
849
|
|
|
824
|
-
is_valid, error = self.validate_file_path(to_path)
|
|
850
|
+
is_valid, error, to_path = self.validate_file_path(to_path)
|
|
825
851
|
if not is_valid:
|
|
826
852
|
return {"success": False, "error": f"Destination: {error}"}
|
|
827
853
|
|
|
@@ -888,7 +914,8 @@ class FileOperationsExecutor:
|
|
|
888
914
|
if not content:
|
|
889
915
|
return {"success": False, "error": "Empty content"}
|
|
890
916
|
|
|
891
|
-
|
|
917
|
+
# Allow appending to files in ~/.kollabor-cli/ (skill files for global agents)
|
|
918
|
+
is_valid, error, filepath = self.validate_file_path(filepath, allow_kollabor_config=True)
|
|
892
919
|
if not is_valid:
|
|
893
920
|
return {"success": False, "error": error}
|
|
894
921
|
|
|
@@ -949,7 +976,8 @@ class FileOperationsExecutor:
|
|
|
949
976
|
if not filepath or not pattern:
|
|
950
977
|
return {"success": False, "error": "Missing file or pattern"}
|
|
951
978
|
|
|
952
|
-
|
|
979
|
+
# Allow inserting in files in ~/.kollabor-cli/ (skill files for global agents)
|
|
980
|
+
is_valid, error, filepath = self.validate_file_path(filepath, allow_kollabor_config=True)
|
|
953
981
|
if not is_valid:
|
|
954
982
|
return {"success": False, "error": error}
|
|
955
983
|
|
|
@@ -1041,7 +1069,8 @@ class FileOperationsExecutor:
|
|
|
1041
1069
|
if not filepath or not pattern:
|
|
1042
1070
|
return {"success": False, "error": "Missing file or pattern"}
|
|
1043
1071
|
|
|
1044
|
-
|
|
1072
|
+
# Allow inserting in files in ~/.kollabor-cli/ (skill files for global agents)
|
|
1073
|
+
is_valid, error, filepath = self.validate_file_path(filepath, allow_kollabor_config=True)
|
|
1045
1074
|
if not is_valid:
|
|
1046
1075
|
return {"success": False, "error": error}
|
|
1047
1076
|
|
|
@@ -1129,7 +1158,7 @@ class FileOperationsExecutor:
|
|
|
1129
1158
|
if not dir_path:
|
|
1130
1159
|
return {"success": False, "error": "Missing directory path"}
|
|
1131
1160
|
|
|
1132
|
-
is_valid, error = self.validate_file_path(dir_path)
|
|
1161
|
+
is_valid, error, dir_path = self.validate_file_path(dir_path)
|
|
1133
1162
|
if not is_valid:
|
|
1134
1163
|
return {"success": False, "error": error}
|
|
1135
1164
|
|
|
@@ -1176,7 +1205,7 @@ class FileOperationsExecutor:
|
|
|
1176
1205
|
if not dir_path:
|
|
1177
1206
|
return {"success": False, "error": "Missing directory path"}
|
|
1178
1207
|
|
|
1179
|
-
is_valid, error = self.validate_file_path(dir_path)
|
|
1208
|
+
is_valid, error, dir_path = self.validate_file_path(dir_path)
|
|
1180
1209
|
if not is_valid:
|
|
1181
1210
|
return {"success": False, "error": error}
|
|
1182
1211
|
|
|
@@ -1237,12 +1266,15 @@ class FileOperationsExecutor:
|
|
|
1237
1266
|
"""
|
|
1238
1267
|
filepath = operation.get("file")
|
|
1239
1268
|
lines_spec = operation.get("lines") # Optional: "10-20"
|
|
1269
|
+
offset = operation.get("offset") # Optional: line offset (0-indexed)
|
|
1270
|
+
limit = operation.get("limit") # Optional: number of lines to read
|
|
1240
1271
|
|
|
1241
1272
|
# Validation
|
|
1242
1273
|
if not filepath:
|
|
1243
1274
|
return {"success": False, "error": "Missing file path"}
|
|
1244
1275
|
|
|
1245
|
-
|
|
1276
|
+
# Allow reading from ~/.kollabor-cli/ (agent/skill files)
|
|
1277
|
+
is_valid, error, filepath = self.validate_file_path(filepath, allow_kollabor_config=True)
|
|
1246
1278
|
if not is_valid:
|
|
1247
1279
|
return {"success": False, "error": error}
|
|
1248
1280
|
|
|
@@ -1275,9 +1307,29 @@ class FileOperationsExecutor:
|
|
|
1275
1307
|
}
|
|
1276
1308
|
|
|
1277
1309
|
# Count total lines for display
|
|
1278
|
-
|
|
1310
|
+
all_lines = content.split('\n')
|
|
1311
|
+
total_lines = len(all_lines)
|
|
1312
|
+
|
|
1313
|
+
# Handle offset/limit if specified (Claude Code style)
|
|
1314
|
+
if offset is not None or limit is not None:
|
|
1315
|
+
start_line = offset if offset is not None else 0
|
|
1316
|
+
end_line = start_line + limit if limit is not None else total_lines
|
|
1317
|
+
end_line = min(end_line, total_lines)
|
|
1318
|
+
|
|
1319
|
+
selected_lines = all_lines[start_line:end_line]
|
|
1320
|
+
content = '\n'.join(selected_lines)
|
|
1321
|
+
line_count = len(selected_lines)
|
|
1322
|
+
|
|
1323
|
+
# Calculate 1-indexed display range
|
|
1324
|
+
display_start = start_line + 1
|
|
1325
|
+
display_end = start_line + line_count
|
|
1326
|
+
|
|
1327
|
+
return {
|
|
1328
|
+
"success": True,
|
|
1329
|
+
"output": f"✓ Read {line_count} lines from {filepath} (lines {display_start}-{display_end}):\n\n{content}"
|
|
1330
|
+
}
|
|
1279
1331
|
|
|
1280
|
-
# Handle line range if specified
|
|
1332
|
+
# Handle line range if specified (lines="10-20" style)
|
|
1281
1333
|
if lines_spec:
|
|
1282
1334
|
try:
|
|
1283
1335
|
if '-' in lines_spec:
|
|
@@ -1288,8 +1340,7 @@ class FileOperationsExecutor:
|
|
|
1288
1340
|
start_line = int(lines_spec.strip()) - 1
|
|
1289
1341
|
end_line = start_line + 1
|
|
1290
1342
|
|
|
1291
|
-
|
|
1292
|
-
selected_lines = lines[start_line:end_line]
|
|
1343
|
+
selected_lines = all_lines[start_line:end_line]
|
|
1293
1344
|
content = '\n'.join(selected_lines)
|
|
1294
1345
|
line_count = len(selected_lines)
|
|
1295
1346
|
|
|
@@ -1328,7 +1379,8 @@ class FileOperationsExecutor:
|
|
|
1328
1379
|
if not pattern:
|
|
1329
1380
|
return {"success": False, "error": "Missing search pattern"}
|
|
1330
1381
|
|
|
1331
|
-
|
|
1382
|
+
# Allow grepping from ~/.kollabor-cli/ (agent/skill files)
|
|
1383
|
+
is_valid, error, filepath = self.validate_file_path(filepath, allow_kollabor_config=True)
|
|
1332
1384
|
if not is_valid:
|
|
1333
1385
|
return {"success": False, "error": error}
|
|
1334
1386
|
|