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.
Files changed (192) hide show
  1. agents/__init__.py +2 -0
  2. agents/coder/__init__.py +0 -0
  3. agents/coder/agent.json +4 -0
  4. agents/coder/api-integration.md +2150 -0
  5. agents/coder/cli-pretty.md +765 -0
  6. agents/coder/code-review.md +1092 -0
  7. agents/coder/database-design.md +1525 -0
  8. agents/coder/debugging.md +1102 -0
  9. agents/coder/dependency-management.md +1397 -0
  10. agents/coder/git-workflow.md +1099 -0
  11. agents/coder/refactoring.md +1454 -0
  12. agents/coder/security-hardening.md +1732 -0
  13. agents/coder/system_prompt.md +1448 -0
  14. agents/coder/tdd.md +1367 -0
  15. agents/creative-writer/__init__.py +0 -0
  16. agents/creative-writer/agent.json +4 -0
  17. agents/creative-writer/character-development.md +1852 -0
  18. agents/creative-writer/dialogue-craft.md +1122 -0
  19. agents/creative-writer/plot-structure.md +1073 -0
  20. agents/creative-writer/revision-editing.md +1484 -0
  21. agents/creative-writer/system_prompt.md +690 -0
  22. agents/creative-writer/worldbuilding.md +2049 -0
  23. agents/data-analyst/__init__.py +30 -0
  24. agents/data-analyst/agent.json +4 -0
  25. agents/data-analyst/data-visualization.md +992 -0
  26. agents/data-analyst/exploratory-data-analysis.md +1110 -0
  27. agents/data-analyst/pandas-data-manipulation.md +1081 -0
  28. agents/data-analyst/sql-query-optimization.md +881 -0
  29. agents/data-analyst/statistical-analysis.md +1118 -0
  30. agents/data-analyst/system_prompt.md +928 -0
  31. agents/default/__init__.py +0 -0
  32. agents/default/agent.json +4 -0
  33. agents/default/dead-code.md +794 -0
  34. agents/default/explore-agent-system.md +585 -0
  35. agents/default/system_prompt.md +1448 -0
  36. agents/kollabor/__init__.py +0 -0
  37. agents/kollabor/analyze-plugin-lifecycle.md +175 -0
  38. agents/kollabor/analyze-terminal-rendering.md +388 -0
  39. agents/kollabor/code-review.md +1092 -0
  40. agents/kollabor/debug-mcp-integration.md +521 -0
  41. agents/kollabor/debug-plugin-hooks.md +547 -0
  42. agents/kollabor/debugging.md +1102 -0
  43. agents/kollabor/dependency-management.md +1397 -0
  44. agents/kollabor/git-workflow.md +1099 -0
  45. agents/kollabor/inspect-llm-conversation.md +148 -0
  46. agents/kollabor/monitor-event-bus.md +558 -0
  47. agents/kollabor/profile-performance.md +576 -0
  48. agents/kollabor/refactoring.md +1454 -0
  49. agents/kollabor/system_prompt copy.md +1448 -0
  50. agents/kollabor/system_prompt.md +757 -0
  51. agents/kollabor/trace-command-execution.md +178 -0
  52. agents/kollabor/validate-config.md +879 -0
  53. agents/research/__init__.py +0 -0
  54. agents/research/agent.json +4 -0
  55. agents/research/architecture-mapping.md +1099 -0
  56. agents/research/codebase-analysis.md +1077 -0
  57. agents/research/dependency-audit.md +1027 -0
  58. agents/research/performance-profiling.md +1047 -0
  59. agents/research/security-review.md +1359 -0
  60. agents/research/system_prompt.md +492 -0
  61. agents/technical-writer/__init__.py +0 -0
  62. agents/technical-writer/agent.json +4 -0
  63. agents/technical-writer/api-documentation.md +2328 -0
  64. agents/technical-writer/changelog-management.md +1181 -0
  65. agents/technical-writer/readme-writing.md +1360 -0
  66. agents/technical-writer/style-guide.md +1410 -0
  67. agents/technical-writer/system_prompt.md +653 -0
  68. agents/technical-writer/tutorial-creation.md +1448 -0
  69. core/__init__.py +0 -2
  70. core/application.py +343 -88
  71. core/cli.py +229 -10
  72. core/commands/menu_renderer.py +463 -59
  73. core/commands/registry.py +14 -9
  74. core/commands/system_commands.py +2461 -14
  75. core/config/loader.py +151 -37
  76. core/config/service.py +18 -6
  77. core/events/bus.py +29 -9
  78. core/events/executor.py +205 -75
  79. core/events/models.py +27 -8
  80. core/fullscreen/command_integration.py +20 -24
  81. core/fullscreen/components/__init__.py +10 -1
  82. core/fullscreen/components/matrix_components.py +1 -2
  83. core/fullscreen/components/space_shooter_components.py +654 -0
  84. core/fullscreen/plugin.py +5 -0
  85. core/fullscreen/renderer.py +52 -13
  86. core/fullscreen/session.py +52 -15
  87. core/io/__init__.py +29 -5
  88. core/io/buffer_manager.py +6 -1
  89. core/io/config_status_view.py +7 -29
  90. core/io/core_status_views.py +267 -347
  91. core/io/input/__init__.py +25 -0
  92. core/io/input/command_mode_handler.py +711 -0
  93. core/io/input/display_controller.py +128 -0
  94. core/io/input/hook_registrar.py +286 -0
  95. core/io/input/input_loop_manager.py +421 -0
  96. core/io/input/key_press_handler.py +502 -0
  97. core/io/input/modal_controller.py +1011 -0
  98. core/io/input/paste_processor.py +339 -0
  99. core/io/input/status_modal_renderer.py +184 -0
  100. core/io/input_errors.py +5 -1
  101. core/io/input_handler.py +211 -2452
  102. core/io/key_parser.py +7 -0
  103. core/io/layout.py +15 -3
  104. core/io/message_coordinator.py +111 -2
  105. core/io/message_renderer.py +129 -4
  106. core/io/status_renderer.py +147 -607
  107. core/io/terminal_renderer.py +97 -51
  108. core/io/terminal_state.py +21 -4
  109. core/io/visual_effects.py +816 -165
  110. core/llm/agent_manager.py +1063 -0
  111. core/llm/api_adapters/__init__.py +44 -0
  112. core/llm/api_adapters/anthropic_adapter.py +432 -0
  113. core/llm/api_adapters/base.py +241 -0
  114. core/llm/api_adapters/openai_adapter.py +326 -0
  115. core/llm/api_communication_service.py +167 -113
  116. core/llm/conversation_logger.py +322 -16
  117. core/llm/conversation_manager.py +556 -30
  118. core/llm/file_operations_executor.py +84 -32
  119. core/llm/llm_service.py +934 -103
  120. core/llm/mcp_integration.py +541 -57
  121. core/llm/message_display_service.py +135 -18
  122. core/llm/plugin_sdk.py +1 -2
  123. core/llm/profile_manager.py +1183 -0
  124. core/llm/response_parser.py +274 -56
  125. core/llm/response_processor.py +16 -3
  126. core/llm/tool_executor.py +6 -1
  127. core/logging/__init__.py +2 -0
  128. core/logging/setup.py +34 -6
  129. core/models/resume.py +54 -0
  130. core/plugins/__init__.py +4 -2
  131. core/plugins/base.py +127 -0
  132. core/plugins/collector.py +23 -161
  133. core/plugins/discovery.py +37 -3
  134. core/plugins/factory.py +6 -12
  135. core/plugins/registry.py +5 -17
  136. core/ui/config_widgets.py +128 -28
  137. core/ui/live_modal_renderer.py +2 -1
  138. core/ui/modal_actions.py +5 -0
  139. core/ui/modal_overlay_renderer.py +0 -60
  140. core/ui/modal_renderer.py +268 -7
  141. core/ui/modal_state_manager.py +29 -4
  142. core/ui/widgets/base_widget.py +7 -0
  143. core/updates/__init__.py +10 -0
  144. core/updates/version_check_service.py +348 -0
  145. core/updates/version_comparator.py +103 -0
  146. core/utils/config_utils.py +685 -526
  147. core/utils/plugin_utils.py +1 -1
  148. core/utils/session_naming.py +111 -0
  149. fonts/LICENSE +21 -0
  150. fonts/README.md +46 -0
  151. fonts/SymbolsNerdFont-Regular.ttf +0 -0
  152. fonts/SymbolsNerdFontMono-Regular.ttf +0 -0
  153. fonts/__init__.py +44 -0
  154. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/METADATA +54 -4
  155. kollabor-0.4.15.dist-info/RECORD +228 -0
  156. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/top_level.txt +2 -0
  157. plugins/agent_orchestrator/__init__.py +39 -0
  158. plugins/agent_orchestrator/activity_monitor.py +181 -0
  159. plugins/agent_orchestrator/file_attacher.py +77 -0
  160. plugins/agent_orchestrator/message_injector.py +135 -0
  161. plugins/agent_orchestrator/models.py +48 -0
  162. plugins/agent_orchestrator/orchestrator.py +403 -0
  163. plugins/agent_orchestrator/plugin.py +976 -0
  164. plugins/agent_orchestrator/xml_parser.py +191 -0
  165. plugins/agent_orchestrator_plugin.py +9 -0
  166. plugins/enhanced_input/box_styles.py +1 -0
  167. plugins/enhanced_input/color_engine.py +19 -4
  168. plugins/enhanced_input/config.py +2 -2
  169. plugins/enhanced_input_plugin.py +61 -11
  170. plugins/fullscreen/__init__.py +6 -2
  171. plugins/fullscreen/example_plugin.py +1035 -222
  172. plugins/fullscreen/setup_wizard_plugin.py +592 -0
  173. plugins/fullscreen/space_shooter_plugin.py +131 -0
  174. plugins/hook_monitoring_plugin.py +436 -78
  175. plugins/query_enhancer_plugin.py +66 -30
  176. plugins/resume_conversation_plugin.py +1494 -0
  177. plugins/save_conversation_plugin.py +98 -32
  178. plugins/system_commands_plugin.py +70 -56
  179. plugins/tmux_plugin.py +154 -78
  180. plugins/workflow_enforcement_plugin.py +94 -92
  181. system_prompt/default.md +952 -886
  182. core/io/input_mode_manager.py +0 -402
  183. core/io/modal_interaction_handler.py +0 -315
  184. core/io/raw_input_processor.py +0 -946
  185. core/storage/__init__.py +0 -5
  186. core/storage/state_manager.py +0 -84
  187. core/ui/widget_integration.py +0 -222
  188. core/utils/key_reader.py +0 -171
  189. kollabor-0.4.9.dist-info/RECORD +0 -128
  190. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/WHEEL +0 -0
  191. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/entry_points.txt +0 -0
  192. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,879 @@
1
+ <!-- Configuration integrity validation - check settings, detect conflicts, verify defaults -->
2
+
3
+ skill name: validate-config
4
+
5
+ purpose:
6
+ validate kollabor configuration integrity, check for missing required settings,
7
+ identify conflicting configurations, and show effective (merged) configuration.
8
+ helps diagnose configuration-related issues before they cause runtime problems.
9
+
10
+
11
+ when to use:
12
+ [ ] application behaving unexpectedly
13
+ [ ] plugin not loading properly
14
+ [ ] changes to config.json not taking effect
15
+ [ ] want to understand effective vs default config
16
+ [ ] setting up kollabor for first time
17
+ [ ] migrating between versions
18
+ [ ] diagnosing plugin configuration issues
19
+
20
+
21
+ methodology:
22
+
23
+ phase 1: config file discovery and structure validation
24
+ locate all config files (local, global, plugin defaults)
25
+ validate json syntax and structure
26
+ check required top-level sections
27
+
28
+ phase 2: setting validation
29
+ verify required llm settings (api_url, model, etc)
30
+ check plugin configurations
31
+ validate data types and value ranges
32
+ identify deprecated or moved settings
33
+
34
+ phase 3: conflict detection
35
+ check for duplicate settings with different values
36
+ identify plugin config conflicts
37
+ detect incompatible setting combinations
38
+
39
+ phase 4: effective config analysis
40
+ show merged configuration (defaults + plugins + user)
41
+ identify which file/layer provides each setting
42
+ highlight user overrides
43
+
44
+
45
+ tools and commands:
46
+
47
+ core files to read:
48
+ <read>file>core/config/loader.py</file>
49
+ <read>file>core/config/manager.py</file>
50
+ <read>file>core/config/plugin_config_manager.py</file>
51
+ <read>file>core/config/plugin_schema.py</file>
52
+ <read>file>core/utils/config_utils.py</file>
53
+
54
+ check config file existence:
55
+ <terminal>ls -la .kollabor-cli/config.json 2>/dev/null || echo "no local config"</terminal>
56
+ <terminal>ls -la ~/.kollabor-cli/config.json 2>/dev/null || echo "no global config"</terminal>
57
+
58
+ view config files:
59
+ <terminal>cat .kollabor-cli/config.json 2>/dev/null</terminal>
60
+ <terminal>cat ~/.kollabor-cli/config.json 2>/dev/null</terminal>
61
+
62
+ validate json syntax:
63
+ <terminal>python -c "import json; json.load(open('.kollabor-cli/config.json'))" 2>&1</terminal>
64
+ <terminal>python -c "import json; json.load(open('~/.kollabor-cli/config.json'))" 2>&1</terminal>
65
+
66
+ find all config-related files:
67
+ <terminal>find .kollabor-cli -name "*.json" -type f 2>/dev/null</terminal>
68
+ <terminal>find ~/.kollabor-cli -name "*.json" -type f 2>/dev/null</terminal>
69
+
70
+ check config in logs:
71
+ <terminal>grep -i "config" .kollabor-cli/logs/kollabor.log | tail -20</terminal>
72
+ <terminal>grep -i "loaded.*config\|merged.*config" .kollabor-cli/logs/kollabor.log</terminal>
73
+
74
+
75
+ configuration system architecture:
76
+
77
+ config manager (core/config/manager.py)
78
+ - config_path: path to config.json file
79
+ - config: in-memory configuration dict
80
+ - load_config_file(): load json from file
81
+ - save_config_file(): save json to file
82
+ - get(key_path, default): dot notation access
83
+ - set(key_path, value): dot notation write
84
+
85
+ config loader (core/config/loader.py)
86
+ - config_manager: base config manager instance
87
+ - plugin_registry: plugin registry for plugin configs
88
+ - plugin_config_manager: dynamic schema manager
89
+ - get_base_config(): returns application defaults
90
+ - get_plugin_configs(): returns merged plugin configs
91
+ - load_complete_config(): returns full merged config
92
+ - _load_user_config_with_fallback(): local -> global priority
93
+
94
+ config priority order (highest to lowest):
95
+ 1. environment variables (kollabor_*)
96
+ 2. local config (.kollabor-cli/config.json in cwd)
97
+ 3. global config (~/.kollabor-cli/config.json)
98
+ 4. plugin-provided defaults
99
+ 5. base application defaults
100
+
101
+ plugin config manager (core/config/plugin_config_manager.py)
102
+ - plugin_schemas: registered plugin config schemas
103
+ - widget_definitions: ui widget definitions
104
+ - discover_plugin_schemas(): find plugin get_config_schema() methods
105
+ - validate_plugin_config(): validate config against schema
106
+ - get_plugin_default_config(): get defaults for a plugin
107
+
108
+
109
+ phase 1: config file discovery and structure validation
110
+
111
+ step 1: locate active config file
112
+
113
+ check which config is being used:
114
+ <terminal>python -c "
115
+ from pathlib import path
116
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
117
+ global = path.home() / '.kollabor-cli' / 'config.json'
118
+ if local.exists():
119
+ print(f'using local: {local}')
120
+ elif global.exists():
121
+ print(f'using global: {global}')
122
+ else:
123
+ print('no config file found - using defaults')
124
+ "</terminal>
125
+
126
+ check for both configs:
127
+ <terminal>ls -la .kollabor-cli/config.json ~/.kollabor-cli/config.json 2>&0</terminal>
128
+
129
+
130
+ step 2: validate json syntax
131
+
132
+ validate local config:
133
+ <terminal>python -c "
134
+ import json, sys
135
+ try:
136
+ with open('.kollabor-cli/config.json') as f:
137
+ data = json.load(f)
138
+ print(f'[ok] valid json, {len(data)} top-level keys')
139
+ except json.jsondecodeerror as e:
140
+ print(f'[error] json syntax error: {e}')
141
+ sys.exit(1)
142
+ except filenotfounderror:
143
+ print('[warn] no local config file')
144
+ "</terminal>
145
+
146
+ validate global config:
147
+ <terminal>python -c "
148
+ import json, sys
149
+ from pathlib import path
150
+ p = path.home() / '.kollabor-cli' / 'config.json'
151
+ try:
152
+ with open(p) as f:
153
+ data = json.load(f)
154
+ print(f'[ok] valid json, {len(data)} top-level keys')
155
+ except json.jsondecodeerror as e:
156
+ print(f'[error] json syntax error: {e}')
157
+ except filenotfounderror:
158
+ print('[warn] no global config file')
159
+ "</terminal>
160
+
161
+
162
+ step 3: check required top-level sections
163
+
164
+ verify config structure:
165
+ <terminal>python -c "
166
+ import json
167
+ from pathlib import path
168
+
169
+ required_sections = ['terminal', 'input', 'logging', 'core', 'plugins', 'application']
170
+
171
+ config_path = None
172
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
173
+ if local.exists():
174
+ config_path = local
175
+ else:
176
+ global = path.home() / '.kollabor-cli' / 'config.json'
177
+ if global.exists():
178
+ config_path = global
179
+
180
+ if not config_path:
181
+ print('[warn] no config file found')
182
+ else:
183
+ with open(config_path) as f:
184
+ config = json.load(f)
185
+
186
+ print('config structure check:')
187
+ for section in required_sections:
188
+ if section in config:
189
+ print(f' [ok] {section}')
190
+ else:
191
+ print(f' [warn] {section} - missing (will use defaults)')
192
+
193
+ # check for extra/unknown sections
194
+ known = required_sections + ['workflow_enforcement', 'performance', 'hooks']
195
+ for key in config.keys():
196
+ if key not in known:
197
+ print(f' [info] {key} - custom section')
198
+ "</terminal>
199
+
200
+
201
+ phase 2: setting validation
202
+
203
+ step 1: verify required llm settings
204
+
205
+ check core llm settings:
206
+ <terminal>python -c "
207
+ import json
208
+ from pathlib import path
209
+
210
+ config_path = none
211
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
212
+ if local.exists():
213
+ config_path = local
214
+ else:
215
+ global = path.home() / '.kollabor-cli' / 'config.json'
216
+ if global.exists():
217
+ config_path = global
218
+
219
+ # check base defaults from loader
220
+ print('checking llm settings...')
221
+
222
+ required_settings = {
223
+ 'core.llm.api_url': 'llm api endpoint url',
224
+ 'core.llm.model': 'model name/identifier',
225
+ 'core.llm.temperature': 'sampling temperature (0.0-1.0)',
226
+ 'core.llm.max_history': 'conversation history limit'
227
+ }
228
+
229
+ if config_path:
230
+ with open(config_path) as f:
231
+ config = json.load(f)
232
+
233
+ print('llm settings in config:')
234
+ for key, desc in required_settings.items():
235
+ parts = key.split('.')
236
+ value = config
237
+ try:
238
+ for part in parts:
239
+ value = value[part]
240
+ print(f' [ok] {key}: {value}')
241
+ except (keyerror, typeerror):
242
+ print(f' [info] {key}: using default')
243
+ else:
244
+ print(' no config file - all settings using defaults')
245
+ "</terminal>
246
+
247
+
248
+ step 2: validate setting values
249
+
250
+ check for invalid values:
251
+ <terminal>python -c "
252
+ import json
253
+ from pathlib import path
254
+
255
+ def validate_config(config):
256
+ warnings = []
257
+ errors = []
258
+
259
+ # check temperature range
260
+ try:
261
+ temp = config.get('core', {}).get('llm', {}).get('temperature', 0.7)
262
+ if not 0.0 <= temp <= 2.0:
263
+ errors.append(f'invalid temperature: {temp} (must be 0.0-2.0)')
264
+ except: pass
265
+
266
+ # check max_history
267
+ try:
268
+ history = config.get('core', {}).get('llm', {}).get('max_history', 90)
269
+ if history < 0 or history > 1000:
270
+ warnings.append(f'unusual max_history: {history}')
271
+ except: pass
272
+
273
+ # check timeout values
274
+ try:
275
+ timeout = config.get('core', {}).get('llm', {}).get('timeout', 0)
276
+ if timeout < 0:
277
+ errors.append(f'invalid timeout: {timeout} (must be >= 0)')
278
+ except: pass
279
+
280
+ # check render_fps
281
+ try:
282
+ fps = config.get('terminal', {}).get('render_fps', 20)
283
+ if fps < 1 or fps > 120:
284
+ warnings.append(f'unusual render_fps: {fps}')
285
+ except: pass
286
+
287
+ return errors, warnings
288
+
289
+ config_path = none
290
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
291
+ if local.exists():
292
+ config_path = local
293
+ else:
294
+ global = path.home() / '.kollabor-cli' / 'config.json'
295
+ if global.exists():
296
+ config_path = global
297
+
298
+ if config_path:
299
+ with open(config_path) as f:
300
+ config = json.load(f)
301
+ errors, warnings = validate_config(config)
302
+
303
+ if errors:
304
+ print('errors:')
305
+ for e in errors:
306
+ print(f' [error] {e}')
307
+
308
+ if warnings:
309
+ print('warnings:')
310
+ for w in warnings:
311
+ print(f' [warn] {w}')
312
+
313
+ if not errors and not warnings:
314
+ print('[ok] all setting values valid')
315
+ else:
316
+ print('[info] no config file - using defaults')
317
+ "</terminal>
318
+
319
+
320
+ step 3: validate plugin configurations
321
+
322
+ check plugin configs:
323
+ <terminal>python -c "
324
+ import json
325
+ from pathlib import path
326
+
327
+ config_path = none
328
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
329
+ if local.exists():
330
+ config_path = local
331
+ else:
332
+ global = path.home() / '.kollabor-cli' / 'config.json'
333
+ if global.exists():
334
+ config_path = global
335
+
336
+ known_plugins = [
337
+ 'enhanced_input', 'system_commands', 'hook_monitoring',
338
+ 'query_enhancer', 'workflow_enforcement', 'fullscreen'
339
+ ]
340
+
341
+ if config_path:
342
+ with open(config_path) as f:
343
+ config = json.load(f)
344
+
345
+ plugins = config.get('plugins', {})
346
+ print('plugin configurations:')
347
+
348
+ for plugin_name in known_plugins:
349
+ if plugin_name in plugins:
350
+ plugin_config = plugins[plugin_name]
351
+ enabled = plugin_config.get('enabled', false)
352
+ status = '[ok]' if enabled else '[info]'
353
+ print(f' {status} {plugin_name}: enabled={enabled}')
354
+ else:
355
+ print(f' [warn] {plugin_name}: not in config (will use defaults)')
356
+
357
+ # check for unknown plugins
358
+ for plugin_name in plugins.keys():
359
+ if plugin_name not in known_plugins:
360
+ print(f' [info] {plugin_name}: custom/unknown plugin')
361
+ else:
362
+ print('[info] no config file - all plugins using defaults')
363
+ "</terminal>
364
+
365
+
366
+ phase 3: conflict detection
367
+
368
+ step 1: check for duplicate settings
369
+
370
+ find settings defined in multiple places:
371
+ <terminal>python -c "
372
+ import json
373
+ from pathlib import path
374
+
375
+ def find_all_configs():
376
+ configs = []
377
+
378
+ # local config
379
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
380
+ if local.exists():
381
+ with open(local) as f:
382
+ configs.append(('local', json.load(f)))
383
+
384
+ # global config
385
+ global = path.home() / '.kollabor-cli' / 'config.json'
386
+ if global.exists():
387
+ with open(global) as f:
388
+ configs.append(('global', json.load(f)))
389
+
390
+ return configs
391
+
392
+ def flatten_config(d, prefix=''):
393
+ items = []
394
+ for k, v in d.items():
395
+ key = f'{prefix}.{k}' if prefix else k
396
+ if isinstance(v, dict):
397
+ items.extend(flatten_config(v, key))
398
+ else:
399
+ items.append((key, v))
400
+ return items
401
+
402
+ configs = find_all_configs()
403
+
404
+ if len(configs) <= 1:
405
+ print('[info] only one config source - no conflicts possible')
406
+ else:
407
+ # collect all settings from all configs
408
+ all_settings = {}
409
+ for name, config in configs:
410
+ for key, value in flatten_config(config):
411
+ if key not in all_settings:
412
+ all_settings[key] = []
413
+ all_settings[key].append((name, value))
414
+
415
+ # find duplicates with different values
416
+ print('potential conflicts (same key, different value):')
417
+ conflicts_found = false
418
+ for key, sources in all_settings.items():
419
+ if len(sources) > 1:
420
+ values = set(str(v) for _, v in sources)
421
+ if len(values) > 1:
422
+ conflicts_found = true
423
+ print(f' [warn] {key}:')
424
+ for source, value in sources:
425
+ print(f' {source}: {value}')
426
+
427
+ if not conflicts_found:
428
+ print('[ok] no conflicting values found')
429
+ "</terminal>
430
+
431
+
432
+ step 2: check plugin config conflicts
433
+
434
+ check for incompatible plugin combinations:
435
+ <terminal>python -c "
436
+ import json
437
+ from pathlib import path
438
+
439
+ config_path = none
440
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
441
+ if local.exists():
442
+ config_path = local
443
+ else:
444
+ global = path.home() / '.kollabor-cli' / 'config.json'
445
+ if global.exists():
446
+ config_path = global
447
+
448
+ # known incompatible combinations
449
+ incompatible_plugins = [
450
+ # workflow_enforcement interferes with normal operation
451
+ ('workflow_enforcement', 'query_enhancer'),
452
+ ]
453
+
454
+ if config_path:
455
+ with open(config_path) as f:
456
+ config = json.load(f)
457
+
458
+ plugins = config.get('plugins', {})
459
+ enabled = [name for name, cfg in plugins.items() if cfg.get('enabled', false)]
460
+
461
+ print('checking plugin compatibility...')
462
+ for p1, p2 in incompatible_plugins:
463
+ if p1 in enabled and p2 in enabled:
464
+ print(f' [warn] {p1} and {p2} may not work well together')
465
+
466
+ # check for duplicate-like plugins
467
+ input_plugins = [p for p in enabled if 'input' in p.lower()]
468
+ if len(input_plugins) > 1:
469
+ print(f' [warn] multiple input-related plugins: {input_plugins}')
470
+
471
+ print('[ok] plugin compatibility check complete')
472
+ else:
473
+ print('[info] no config file')
474
+ "</terminal>
475
+
476
+
477
+ phase 4: effective config analysis
478
+
479
+ step 1: show merged configuration structure
480
+
481
+ display effective config:
482
+ <terminal>python -c "
483
+ import sys
484
+ sys.path.insert(0, '.')
485
+
486
+ from core.config.loader import configloader
487
+ from core.config.manager import configmanager
488
+ from pathlib import path
489
+
490
+ # create config loader
491
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
492
+ manager = configmanager(local)
493
+ loader = configloader(manager)
494
+
495
+ # get complete merged config
496
+ config = loader.load_complete_config()
497
+
498
+ print('effective configuration (merged):')
499
+ print('=' * 50)
500
+
501
+ # show top-level keys
502
+ for key in sorted(config.keys()):
503
+ value = config[key]
504
+ if isinstance(value, dict):
505
+ print(f'{key}:')
506
+ for subkey in sorted(value.keys())[:5]: # show first 5
507
+ print(f' - {subkey}')
508
+ if len(value) > 5:
509
+ print(f' ... and {len(value) - 5} more')
510
+ else:
511
+ print(f'{key}: {value}')
512
+ "</terminal>
513
+
514
+
515
+ step 2: trace setting sources
516
+
517
+ find where a setting comes from:
518
+ <terminal>python -c "
519
+ import sys
520
+ sys.path.insert(0, '.')
521
+
522
+ from core.config.loader import configloader
523
+ from core.config.manager import configmanager
524
+ from pathlib import path
525
+ import json
526
+
527
+ # check each layer
528
+ def get_setting_path(config_dict, path_parts):
529
+ value = config_dict
530
+ for part in path_parts:
531
+ if isinstance(value, dict) and part in value:
532
+ value = value[part]
533
+ else:
534
+ return none
535
+ return value
536
+
537
+ setting = 'core.llm.api_url' # change this to check different settings
538
+ parts = setting.split('.')
539
+
540
+ print(f'tracing setting: {setting}')
541
+ print('-' * 40)
542
+
543
+ # check base defaults
544
+ print('[1] base defaults:')
545
+ loader_instance = configloader(configmanager(path.cwd() / '.kollabor-cli' / 'config.json'))
546
+ base = loader_instance.get_base_config()
547
+ value = get_setting_path(base, parts)
548
+ if value is not none:
549
+ print(f' value: {value}')
550
+
551
+ # check user config
552
+ print('[2] user config:')
553
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
554
+ if local.exists():
555
+ with open(local) as f:
556
+ user = json.load(f)
557
+ value = get_setting_path(user, parts)
558
+ if value is not none:
559
+ print(f' value: {value}')
560
+ print(f' source: {local}')
561
+ else:
562
+ print(' no local config')
563
+
564
+ # final effective value
565
+ print('[3] effective value:')
566
+ effective = loader_instance.load_complete_config()
567
+ value = get_setting_path(effective, parts)
568
+ if value is not none:
569
+ print(f' {value}')
570
+ "</terminal>
571
+
572
+
573
+ step 3: compare config to defaults
574
+
575
+ show user overrides:
576
+ <terminal>python -c "
577
+ import sys
578
+ sys.path.insert(0, '.')
579
+
580
+ from core.config.loader import configloader
581
+ from core.config.manager import configmanager
582
+ from pathlib import path
583
+ import json
584
+
585
+ def compare_configs(default, user):
586
+ differences = []
587
+
588
+ def flatten(d, prefix=''):
589
+ items = {}
590
+ for k, v in d.items():
591
+ key = f'{prefix}.{k}' if prefix else k
592
+ if isinstance(v, dict):
593
+ items.update(flatten(v, key))
594
+ else:
595
+ items[key] = v
596
+ return items
597
+
598
+ flat_default = flatten(default)
599
+ flat_user = flatten(user)
600
+
601
+ # find overrides
602
+ for key in flat_user:
603
+ if key in flat_default:
604
+ if flat_default[key] != flat_user[key]:
605
+ differences.append({
606
+ 'key': key,
607
+ 'default': flat_default[key],
608
+ 'user': flat_user[key]
609
+ })
610
+ else:
611
+ differences.append({
612
+ 'key': key,
613
+ 'default': '(not set)',
614
+ 'user': flat_user[key]
615
+ })
616
+
617
+ return differences
618
+
619
+ print('user overrides vs defaults:')
620
+ print('=' * 50)
621
+
622
+ loader = configloader(configmanager(path.cwd() / '.kollabor-cli' / 'config.json'))
623
+ default = loader.get_base_config()
624
+
625
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
626
+ if local.exists():
627
+ with open(local) as f:
628
+ user = json.load(f)
629
+
630
+ diffs = compare_configs(default, user)
631
+
632
+ if diffs:
633
+ for diff in diffs[:20]: # show first 20
634
+ print(f"{diff['key']}:")
635
+ print(f" default: {diff['default']}")
636
+ print(f" user: {diff['user']}")
637
+
638
+ if len(diffs) > 20:
639
+ print(f'... and {len(diffs) - 20} more differences')
640
+ else:
641
+ print('[ok] config matches defaults')
642
+ else:
643
+ print('[info] no local config file')
644
+ "</terminal>
645
+
646
+
647
+ example workflow:
648
+
649
+ scenario: "kollabor not connecting to llm"
650
+
651
+ step 1: check config file exists
652
+ <terminal>ls -la .kollabor-cli/config.json ~/.kollabor-cli/config.json</terminal>
653
+
654
+ step 2: verify llm settings in config
655
+ <terminal>python -c "
656
+ import json
657
+ from pathlib import path
658
+
659
+ for p in [path.cwd() / '.kollabor-cli' / 'config.json', path.home() / '.kollabor-cli' / 'config.json']:
660
+ if p.exists():
661
+ with open(p) as f:
662
+ cfg = json.load(f)
663
+ llm = cfg.get('core', {}).get('llm', {})
664
+ print(f'file: {p}')
665
+ print(f' api_url: {llm.get(\"api_url\", \"(default)\")}')
666
+ print(f' model: {llm.get(\"model\", \"(default)\")}')
667
+ print(f' api_token: {\"(set)\" if llm.get(\"api_token\") else \"(empty)\"}')
668
+ print()
669
+ "</terminal>
670
+
671
+ step 3: check for syntax errors
672
+ <terminal>python -c "import json; json.load(open('.kollabor-cli/config.json'))"</terminal>
673
+
674
+ step 4: verify effective config
675
+ <terminal>python -c "
676
+ import sys
677
+ sys.path.insert(0, '.')
678
+ from core.config.loader import configloader
679
+ from core.config.manager import configmanager
680
+ from pathlib import path
681
+
682
+ loader = configloader(configmanager(path.cwd() / '.kollabor-cli' / 'config.json'))
683
+ cfg = loader.load_complete_config()
684
+ print('effective api_url:', cfg['core']['llm']['api_url'])
685
+ "</terminal>
686
+
687
+
688
+ example workflow 2:
689
+
690
+ scenario: "plugin configuration not taking effect"
691
+
692
+ step 1: check plugin in config
693
+ <terminal>grep -a 10 '"enhanced_input"' .kollabor-cli/config.json</terminal>
694
+
695
+ step 2: verify enabled status
696
+ <terminal>python -c "
697
+ import json
698
+ with open('.kollabor-cli/config.json') as f:
699
+ cfg = json.load(f)
700
+ print('enhanced_input enabled:', cfg.get('plugins', {}).get('enhanced_input', {}).get('enabled', false))
701
+ "</terminal>
702
+
703
+ step 3: check for plugin config errors in logs
704
+ <terminal>grep -i "plugin.*error\|plugin.*fail" .kollabor-cli/logs/kollabor.log | tail -20</terminal>
705
+
706
+
707
+ troubleshooting tips:
708
+
709
+ tip 1: config changes not taking effect
710
+ - verify editing correct config file (check local vs global)
711
+ - json syntax errors will cause silent fallback to defaults
712
+ - some settings require application restart
713
+ - check logs for config loading errors
714
+
715
+ tip 2: missing expected settings
716
+ - not all settings need to be in config.json
717
+ - defaults come from core/config/loader.py:get_base_config()
718
+ - plugins can provide defaults via get_config_schema()
719
+ - check logs for "using default" messages
720
+
721
+ tip 3: plugin configuration issues
722
+ - plugins must be registered in plugins section
723
+ - each plugin needs "enabled" boolean
724
+ - plugin configs merge with defaults, don't need all keys
725
+ - check plugin's get_default_config() for expected structure
726
+
727
+ tip 4: understanding priority
728
+ - local (.kollabor-cli/config.json) overrides global (~/.kollabor-cli/config.json)
729
+ - user config overrides plugin defaults
730
+ - plugin defaults override base defaults
731
+ - env vars (kollabor_*) override everything
732
+
733
+ tip 5: debugging config loading
734
+ - set log level to debug: "logging": {"level": "debug"}
735
+ - check logs for "loaded config" messages
736
+ - look for "merged configuration" entries
737
+ - errors during config load fall back to defaults silently
738
+
739
+ tip 6: common config mistakes
740
+ - trailing comma in json (invalid syntax)
741
+ - using single quotes instead of double quotes
742
+ - missing closing brace }
743
+ - wrong data type (string instead of number)
744
+ - incorrect nested structure (core.llm vs core:llm)
745
+
746
+
747
+ expected output:
748
+
749
+ when this skill executes successfully, you should be able to:
750
+
751
+ [ ] locate and identify active config file
752
+ [ ] validate json syntax of config files
753
+ [ ] verify required settings are present
754
+ [ ] detect conflicting configuration values
755
+ [ ] understand effective vs default configuration
756
+ [ ] trace where each setting comes from
757
+ [ ] identify user overrides vs defaults
758
+ [ ] diagnose plugin configuration issues
759
+
760
+
761
+ quick validation commands:
762
+
763
+ basic health check:
764
+ <terminal>python -c "
765
+ import sys, json
766
+ from pathlib import path
767
+
768
+ checks = []
769
+
770
+ # check local config
771
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
772
+ if local.exists():
773
+ try:
774
+ with open(local) as f:
775
+ json.load(f)
776
+ checks.append(('[ok]', 'local config exists and valid'))
777
+ except json.jsondecodeerror as e:
778
+ checks.append(('[error]', f'local config has invalid json: {e}'))
779
+ except exception as e:
780
+ checks.append(('[error]', f'local config error: {e}'))
781
+ else:
782
+ checks.append(('[info]', 'no local config'))
783
+
784
+ # check global config
785
+ global = path.home() / '.kollabor-cli' / 'config.json'
786
+ if global.exists():
787
+ try:
788
+ with open(global) as f:
789
+ json.load(f)
790
+ checks.append(('[ok]', 'global config exists and valid'))
791
+ except json.jsondecodeerror as e:
792
+ checks.append(('[error]', f'global config has invalid json: {e}'))
793
+ except exception as e:
794
+ checks.append(('[error]', f'global config error: {e}'))
795
+ else:
796
+ checks.append(('[info]', 'no global config'))
797
+
798
+ # print results
799
+ for status, msg in checks:
800
+ print(f'{status} {msg}')
801
+ "</terminal>
802
+
803
+ full validation report:
804
+ <terminal>python -c "
805
+ import sys
806
+ sys.path.insert(0, '.')
807
+ from pathlib import path
808
+ import json
809
+
810
+ print('=' * 60)
811
+ print('kollabor configuration validation report')
812
+ print('=' * 60)
813
+
814
+ # check config files
815
+ local = path.cwd() / '.kollabor-cli' / 'config.json'
816
+ global = path.home() / '.kollabor-cli' / 'config.json'
817
+
818
+ print('\n[1] config files:')
819
+ if local.exists():
820
+ print(' [ok] local config: .kollabor-cli/config.json')
821
+ else:
822
+ print(' [info] no local config')
823
+
824
+ if global.exists():
825
+ print(' [ok] global config: ~/.kollabor-cli/config.json')
826
+ else:
827
+ print(' [info] no global config')
828
+
829
+ # validate syntax
830
+ print('\n[2] json syntax:')
831
+ for name, path in [('local', local), ('global', global)]:
832
+ if path.exists():
833
+ try:
834
+ with open(path) as f:
835
+ data = json.load(f)
836
+ print(f' [ok] {name}: valid json')
837
+ except json.jsondecodeerror as e:
838
+ print(f' [error] {name}: {e}')
839
+
840
+ # check structure
841
+ print('\n[3] config structure:')
842
+ config_path = local if local.exists() else (global if global.exists() else none)
843
+ if config_path:
844
+ with open(config_path) as f:
845
+ config = json.load(f)
846
+
847
+ required = ['terminal', 'input', 'logging', 'core', 'plugins']
848
+ for section in required:
849
+ if section in config:
850
+ print(f' [ok] {section}')
851
+ else:
852
+ print(f' [warn] {section}: missing (defaults used)')
853
+
854
+ print('\n[4] summary:')
855
+ if local.exists() or global.exists():
856
+ print(' [ok] configuration file(s) found')
857
+ print(' run specific validation phases for detailed analysis')
858
+ else:
859
+ print(' [info] no config files - using application defaults')
860
+ print(' config is optional, defaults will be used')
861
+
862
+ print('\n' + '=' * 60)
863
+ "</terminal>
864
+
865
+
866
+ status tags reference:
867
+
868
+ [ok] configuration is valid
869
+ [warn] potential issue that should be reviewed
870
+ [error] definite problem that needs fixing
871
+ [info] informational message
872
+ [todo] action required
873
+
874
+ common exit conditions:
875
+
876
+ [ok] all validations passed
877
+ [ok] issues identified and resolved
878
+ [warn] non-critical issues found
879
+ [error] critical configuration errors found