clink-cli 0.2.1__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 (141) hide show
  1. clink/__init__.py +19 -0
  2. clink/agents/__init__.py +30 -0
  3. clink/agents/base.py +70 -0
  4. clink/agents/claude.py +7 -0
  5. clink/agents/codex.py +7 -0
  6. clink/agents/gemini.py +7 -0
  7. clink/allowed_roots.py +356 -0
  8. clink/backend.py +765 -0
  9. clink/cli.py +594 -0
  10. clink/constants.py +78 -0
  11. clink/contracts.py +167 -0
  12. clink/files.py +70 -0
  13. clink/generation.py +274 -0
  14. clink/generation_capabilities.py +207 -0
  15. clink/generation_contracts.py +214 -0
  16. clink/generation_policy.py +174 -0
  17. clink/models.py +243 -0
  18. clink/native.py +409 -0
  19. clink/native_adapters.py +244 -0
  20. clink/native_contracts.py +68 -0
  21. clink/native_generation.py +421 -0
  22. clink/native_generation_claude_policy.py +59 -0
  23. clink/native_generation_contracts.py +264 -0
  24. clink/native_generation_families.py +218 -0
  25. clink/native_generation_family_policy.py +14 -0
  26. clink/native_generation_files.py +153 -0
  27. clink/native_generation_policy.py +82 -0
  28. clink/native_policy.py +86 -0
  29. clink/parsers/__init__.py +34 -0
  30. clink/parsers/agy.py +53 -0
  31. clink/parsers/agy_native.py +161 -0
  32. clink/parsers/agy_native_generation.py +189 -0
  33. clink/parsers/base.py +209 -0
  34. clink/parsers/claude.py +104 -0
  35. clink/parsers/claude_native.py +113 -0
  36. clink/parsers/claude_native_generation.py +346 -0
  37. clink/parsers/codex.py +172 -0
  38. clink/parsers/codex_generation.py +212 -0
  39. clink/parsers/codex_native.py +236 -0
  40. clink/parsers/codex_native_generation.py +367 -0
  41. clink/parsers/gemini.py +110 -0
  42. clink/parsers/grok.py +63 -0
  43. clink/parsers/grok_native.py +91 -0
  44. clink/parsers/grok_native_generation.py +157 -0
  45. clink/policy.py +180 -0
  46. clink/registry.py +544 -0
  47. clink/resources/CODEX-LICENSE +201 -0
  48. clink/resources/CODEX-NOTICE +6 -0
  49. clink/resources/PROVENANCE.md +16 -0
  50. clink/resources/codex-0.166.0-models-direct.json +1284 -0
  51. clink/resources/codex-0.166.0-models-generation.json +1269 -0
  52. clink/resources/native-agy-1.4.12-admission.json +746 -0
  53. clink/resources/native-claude-2.1.304-admission.json +99 -0
  54. clink/resources/native-generation-claude-2.1.304-admission.json +277 -0
  55. clink/resources/native-generation-codex-0.166.0-admission.json +309 -0
  56. clink/resources/native-generation-grok-1.0.70-admission.json +329 -0
  57. clink/resources/native-grok-1.0.70-admission.json +644 -0
  58. clink/runner.py +303 -0
  59. clink/setup.py +399 -0
  60. clink/tasks.py +695 -0
  61. clink_cli-0.2.1.dist-info/METADATA +225 -0
  62. clink_cli-0.2.1.dist-info/RECORD +141 -0
  63. clink_cli-0.2.1.dist-info/WHEEL +5 -0
  64. clink_cli-0.2.1.dist-info/entry_points.txt +3 -0
  65. clink_cli-0.2.1.dist-info/licenses/LICENSE +197 -0
  66. clink_cli-0.2.1.dist-info/licenses/clink/resources/CODEX-LICENSE +201 -0
  67. clink_cli-0.2.1.dist-info/licenses/clink/resources/CODEX-NOTICE +6 -0
  68. clink_cli-0.2.1.dist-info/top_level.txt +7 -0
  69. conf/__init__.py +1 -0
  70. conf/cli_clients/agy.json +40 -0
  71. conf/cli_clients/claude.json +39 -0
  72. conf/cli_clients/codex.json +40 -0
  73. conf/cli_clients/gemini.json +23 -0
  74. conf/cli_clients/grok.json +40 -0
  75. config.py +40 -0
  76. server.py +896 -0
  77. systemprompts/__init__.py +35 -0
  78. systemprompts/analyze_prompt.py +87 -0
  79. systemprompts/chat_prompt.py +57 -0
  80. systemprompts/clink/codex_codereviewer.txt +8 -0
  81. systemprompts/clink/default.txt +8 -0
  82. systemprompts/clink/default_codereviewer.txt +8 -0
  83. systemprompts/clink/default_planner.txt +7 -0
  84. systemprompts/clink/native_codereviewer.txt +1 -0
  85. systemprompts/clink/native_default.txt +1 -0
  86. systemprompts/clink/native_planner.txt +1 -0
  87. systemprompts/codereview_prompt.py +91 -0
  88. systemprompts/consensus_prompt.py +120 -0
  89. systemprompts/debug_prompt.py +150 -0
  90. systemprompts/docgen_prompt.py +252 -0
  91. systemprompts/generate_code_prompt.py +181 -0
  92. systemprompts/planner_prompt.py +127 -0
  93. systemprompts/precommit_prompt.py +179 -0
  94. systemprompts/refactor_prompt.py +323 -0
  95. systemprompts/secaudit_prompt.py +420 -0
  96. systemprompts/testgen_prompt.py +133 -0
  97. systemprompts/thinkdeep_prompt.py +55 -0
  98. systemprompts/tracer_prompt.py +145 -0
  99. tools/__init__.py +43 -0
  100. tools/analyze.py +583 -0
  101. tools/apilookup.py +97 -0
  102. tools/challenge.py +198 -0
  103. tools/chat.py +187 -0
  104. tools/clink.py +130 -0
  105. tools/codereview.py +724 -0
  106. tools/consensus.py +790 -0
  107. tools/debug.py +573 -0
  108. tools/docgen.py +577 -0
  109. tools/listmodels.py +48 -0
  110. tools/models.py +373 -0
  111. tools/planner.py +533 -0
  112. tools/precommit.py +776 -0
  113. tools/refactor.py +645 -0
  114. tools/secaudit.py +685 -0
  115. tools/shared/__init__.py +19 -0
  116. tools/shared/base_models.py +167 -0
  117. tools/shared/base_tool.py +659 -0
  118. tools/shared/exceptions.py +20 -0
  119. tools/shared/schema_builders.py +159 -0
  120. tools/simple/__init__.py +18 -0
  121. tools/simple/base.py +539 -0
  122. tools/testgen.py +513 -0
  123. tools/thinkdeep.py +586 -0
  124. tools/tracer.py +763 -0
  125. tools/version.py +53 -0
  126. tools/workflow/__init__.py +22 -0
  127. tools/workflow/base.py +448 -0
  128. tools/workflow/schema_builders.py +166 -0
  129. tools/workflow/workflow_mixin.py +1195 -0
  130. utils/__init__.py +21 -0
  131. utils/call_state.py +349 -0
  132. utils/client_info.py +293 -0
  133. utils/consensus_manifest.py +131 -0
  134. utils/conversation_memory.py +582 -0
  135. utils/env.py +111 -0
  136. utils/file_types.py +271 -0
  137. utils/file_utils.py +803 -0
  138. utils/image_utils.py +94 -0
  139. utils/security_config.py +163 -0
  140. utils/storage_backend.py +177 -0
  141. utils/token_utils.py +54 -0
tools/tracer.py ADDED
@@ -0,0 +1,763 @@
1
+ """
2
+ Tracer Workflow tool - Step-by-step code tracing and dependency analysis
3
+
4
+ This tool provides a structured workflow for comprehensive code tracing and analysis.
5
+ It guides the CLI agent through systematic investigation steps with forced pauses between each step
6
+ to ensure thorough code examination, dependency mapping, and execution flow analysis before proceeding.
7
+
8
+ The tracer guides users through sequential code analysis with full context awareness and
9
+ the ability to revise and adapt as understanding deepens.
10
+
11
+ Key features:
12
+ - Sequential tracing with systematic investigation workflow
13
+ - Support for precision tracing (execution flow) and dependencies tracing (structural relationships)
14
+ - Self-contained completion with detailed output formatting instructions
15
+ - Context-aware analysis that builds understanding step by step
16
+ - No external expert analysis needed - provides comprehensive guidance internally
17
+
18
+ Perfect for: method/function execution flow analysis, dependency mapping, call chain tracing,
19
+ structural relationship analysis, architectural understanding, and code comprehension.
20
+ """
21
+
22
+ import logging
23
+ from typing import TYPE_CHECKING, Any, Literal, Optional
24
+
25
+ from pydantic import Field, field_validator
26
+
27
+ if TYPE_CHECKING:
28
+ from tools.models import ToolModelCategory
29
+
30
+ from config import TEMPERATURE_ANALYTICAL
31
+ from systemprompts import TRACER_PROMPT
32
+ from tools.shared.base_models import WorkflowRequest
33
+
34
+ from .workflow.base import WorkflowTool
35
+
36
+ logger = logging.getLogger(__name__)
37
+
38
+ # Tool-specific field descriptions for tracer workflow
39
+ TRACER_WORKFLOW_FIELD_DESCRIPTIONS = {
40
+ "step": (
41
+ "The plan for the current tracing step. Step 1: State the tracing strategy. Later steps: Report findings and adapt the plan. "
42
+ "CRITICAL: For 'precision' mode, focus on execution flow and call chains. For 'dependencies' mode, focus on structural relationships. "
43
+ "If trace_mode is 'ask' in step 1, you MUST prompt the user to choose a mode."
44
+ ),
45
+ "step_number": (
46
+ "The index of the current step in the tracing sequence, beginning at 1. Each step should build upon or "
47
+ "revise the previous one."
48
+ ),
49
+ "total_steps": (
50
+ "Your current estimate for how many steps will be needed to complete the tracing analysis. "
51
+ "Adjust as new findings emerge."
52
+ ),
53
+ "next_step_required": (
54
+ "Set to true if you plan to continue the investigation with another step. False means you believe the "
55
+ "tracing analysis is complete and ready for final output formatting."
56
+ ),
57
+ "findings": (
58
+ "Summary of discoveries from this step, including execution paths, dependency relationships, call chains, and structural patterns. "
59
+ "IMPORTANT: Document both direct (immediate calls) and indirect (transitive, side effects) relationships."
60
+ ),
61
+ "files_checked": (
62
+ "List all files examined (absolute paths). Include even ruled-out files to track exploration path."
63
+ ),
64
+ "relevant_files": (
65
+ "Subset of files_checked directly relevant to the tracing target (absolute paths). Include implementation files, "
66
+ "dependencies, or files demonstrating key relationships."
67
+ ),
68
+ "relevant_context": (
69
+ "List methods/functions central to the tracing analysis, in 'ClassName.methodName' or 'functionName' format. "
70
+ "Prioritize those in the execution flow or dependency chain."
71
+ ),
72
+ "confidence": (
73
+ "Your confidence in the tracing analysis. Use: 'exploring', 'low', 'medium', 'high', 'very_high', 'almost_certain', 'certain'. "
74
+ "CRITICAL: 'certain' implies the analysis is 100% complete locally and PREVENTS external model validation."
75
+ ),
76
+ "trace_mode": "Type of tracing: 'ask' (default - prompts user to choose mode), 'precision' (execution flow) or 'dependencies' (structural relationships)",
77
+ "target_description": (
78
+ "Description of what to trace and WHY. Include context about what you're trying to understand or analyze."
79
+ ),
80
+ "images": ("Optional paths to architecture diagrams or flow charts that help understand the tracing context."),
81
+ }
82
+
83
+
84
+ class TracerRequest(WorkflowRequest):
85
+ """Request model for tracer workflow investigation steps"""
86
+
87
+ # Required fields for each investigation step
88
+ step: str = Field(..., description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["step"])
89
+ step_number: int = Field(..., description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["step_number"])
90
+ total_steps: int = Field(..., description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["total_steps"])
91
+ next_step_required: bool = Field(..., description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["next_step_required"])
92
+
93
+ # Investigation tracking fields
94
+ findings: str = Field(..., description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["findings"])
95
+ files_checked: list[str] = Field(
96
+ default_factory=list, description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["files_checked"]
97
+ )
98
+ relevant_files: list[str] = Field(
99
+ default_factory=list, description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["relevant_files"]
100
+ )
101
+ relevant_context: list[str] = Field(
102
+ default_factory=list, description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["relevant_context"]
103
+ )
104
+ confidence: Optional[str] = Field("exploring", description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["confidence"])
105
+
106
+ # Tracer-specific fields (used in step 1 to initialize)
107
+ trace_mode: Optional[Literal["precision", "dependencies", "ask"]] = Field(
108
+ "ask", description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["trace_mode"]
109
+ )
110
+ target_description: Optional[str] = Field(
111
+ None, description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["target_description"]
112
+ )
113
+ images: Optional[list[str]] = Field(default=None, description=TRACER_WORKFLOW_FIELD_DESCRIPTIONS["images"])
114
+
115
+ # Exclude fields not relevant to tracing workflow
116
+ issues_found: list[dict] = Field(default_factory=list, exclude=True, description="Tracing doesn't track issues")
117
+ hypothesis: Optional[str] = Field(default=None, exclude=True, description="Tracing doesn't use hypothesis")
118
+ # Exclude other non-tracing fields
119
+ temperature: Optional[float] = Field(default=None, exclude=True)
120
+ thinking_mode: Optional[str] = Field(default=None, exclude=True)
121
+ use_assistant_model: Optional[bool] = Field(default=False, exclude=True, description="Tracing is self-contained")
122
+
123
+ @field_validator("step_number")
124
+ @classmethod
125
+ def validate_step_number(cls, v):
126
+ if v < 1:
127
+ raise ValueError("step_number must be at least 1")
128
+ return v
129
+
130
+ @field_validator("total_steps")
131
+ @classmethod
132
+ def validate_total_steps(cls, v):
133
+ if v < 1:
134
+ raise ValueError("total_steps must be at least 1")
135
+ return v
136
+
137
+
138
+ class TracerTool(WorkflowTool):
139
+ """
140
+ Tracer workflow tool for step-by-step code tracing and dependency analysis.
141
+
142
+ This tool implements a structured tracing workflow that guides users through
143
+ methodical investigation steps, ensuring thorough code examination, dependency
144
+ mapping, and execution flow analysis before reaching conclusions. It supports
145
+ both precision tracing (execution flow) and dependencies tracing (structural relationships).
146
+ """
147
+
148
+ def __init__(self):
149
+ super().__init__()
150
+ self.initial_request = None
151
+ self.trace_config = {}
152
+
153
+ def get_name(self) -> str:
154
+ return "tracer"
155
+
156
+ def get_description(self) -> str:
157
+ return (
158
+ "Performs systematic code tracing with modes for execution flow or dependency mapping. "
159
+ "Use for method execution analysis, call chain tracing, dependency mapping, and architectural understanding. "
160
+ "Supports precision mode (execution flow) and dependencies mode (structural relationships)."
161
+ )
162
+
163
+ def get_system_prompt(self) -> str:
164
+ return TRACER_PROMPT
165
+
166
+ def get_default_temperature(self) -> float:
167
+ return TEMPERATURE_ANALYTICAL
168
+
169
+ def get_model_category(self) -> "ToolModelCategory":
170
+ """Tracer requires analytical reasoning for code analysis"""
171
+ from tools.models import ToolModelCategory
172
+
173
+ return ToolModelCategory.EXTENDED_REASONING
174
+
175
+ def requires_model(self) -> bool:
176
+ """
177
+ Tracer tool doesn't require model resolution at the MCP boundary.
178
+
179
+ The tracer is a structured workflow tool that organizes tracing steps
180
+ and provides detailed output formatting guidance without calling external AI models.
181
+
182
+ Returns:
183
+ bool: False - tracer doesn't need AI model access
184
+ """
185
+ return False
186
+
187
+ def get_workflow_request_model(self):
188
+ """Return the tracer-specific request model."""
189
+ return TracerRequest
190
+
191
+ def get_tool_fields(self) -> dict[str, dict[str, Any]]:
192
+ """Return tracing-specific field definitions beyond the standard workflow fields."""
193
+ return {
194
+ # Tracer-specific fields
195
+ "trace_mode": {
196
+ "type": "string",
197
+ "enum": ["precision", "dependencies", "ask"],
198
+ "description": TRACER_WORKFLOW_FIELD_DESCRIPTIONS["trace_mode"],
199
+ },
200
+ "target_description": {
201
+ "type": "string",
202
+ "description": TRACER_WORKFLOW_FIELD_DESCRIPTIONS["target_description"],
203
+ },
204
+ "images": {
205
+ "type": "array",
206
+ "items": {"type": "string"},
207
+ "description": TRACER_WORKFLOW_FIELD_DESCRIPTIONS["images"],
208
+ },
209
+ }
210
+
211
+ def get_input_schema(self) -> dict[str, Any]:
212
+ """Generate input schema using WorkflowSchemaBuilder with field exclusion."""
213
+ from .workflow.schema_builders import WorkflowSchemaBuilder
214
+
215
+ # Exclude investigation-specific fields that tracing doesn't need
216
+ excluded_workflow_fields = [
217
+ "issues_found", # Tracing doesn't track issues
218
+ "hypothesis", # Tracing doesn't use hypothesis
219
+ ]
220
+
221
+ # Exclude common fields that tracing doesn't need
222
+ excluded_common_fields = [
223
+ "cli_name",
224
+ "role",
225
+ "temperature", # Tracing doesn't need temperature control
226
+ "thinking_mode", # Tracing doesn't need thinking mode
227
+ "absolute_file_paths", # Tracing uses relevant_files instead
228
+ ]
229
+
230
+ return WorkflowSchemaBuilder.build_schema(
231
+ tool_specific_fields=self.get_tool_fields(),
232
+ required_fields=["target_description", "trace_mode"], # Step 1 requires these
233
+ model_field_schema=None,
234
+ auto_mode=False,
235
+ tool_name=self.get_name(),
236
+ excluded_workflow_fields=excluded_workflow_fields,
237
+ excluded_common_fields=excluded_common_fields,
238
+ )
239
+
240
+ # ================================================================================
241
+ # Abstract Methods - Required Implementation from BaseWorkflowMixin
242
+ # ================================================================================
243
+
244
+ def get_required_actions(
245
+ self, step_number: int, confidence: str, findings: str, total_steps: int, request=None
246
+ ) -> list[str]:
247
+ """Define required actions for each tracing phase."""
248
+ if step_number == 1:
249
+ # Check if we're in ask mode and need to prompt for mode selection
250
+ if self.get_trace_mode() == "ask":
251
+ return [
252
+ "MUST ask user to choose between precision or dependencies mode",
253
+ "Explain precision mode: traces execution flow, call chains, and usage patterns (best for methods/functions)",
254
+ "Explain dependencies mode: maps structural relationships and bidirectional dependencies (best for classes/modules)",
255
+ "Wait for user's mode selection before proceeding with investigation",
256
+ ]
257
+
258
+ # Initial tracing investigation tasks (when mode is already selected)
259
+ return [
260
+ "Search for and locate the target method/function/class/module in the codebase",
261
+ "Read and understand the implementation of the target code",
262
+ "Identify the file location, complete signature, and basic structure",
263
+ "Begin mapping immediate relationships (what it calls, what calls it)",
264
+ "Understand the context and purpose of the target code",
265
+ ]
266
+ elif confidence in ["exploring", "low"]:
267
+ # Need deeper investigation
268
+ return [
269
+ "Trace deeper into the execution flow or dependency relationships",
270
+ "Examine how the target code is used throughout the codebase",
271
+ "Map additional layers of dependencies or call chains",
272
+ "Look for conditional execution paths, error handling, and edge cases",
273
+ "Understand the broader architectural context and patterns",
274
+ ]
275
+ elif confidence in ["medium", "high"]:
276
+ # Close to completion - need final verification
277
+ return [
278
+ "Verify completeness of the traced relationships and execution paths",
279
+ "Check for any missed dependencies, usage patterns, or execution branches",
280
+ "Confirm understanding of side effects, state changes, and external interactions",
281
+ "Validate that the tracing covers all significant code relationships",
282
+ "Prepare comprehensive findings for final output formatting",
283
+ ]
284
+ else:
285
+ # General investigation needed
286
+ return [
287
+ "Continue systematic tracing of code relationships and execution paths",
288
+ "Gather more evidence using appropriate code analysis techniques",
289
+ "Test assumptions about code behavior and dependency relationships",
290
+ "Look for patterns that enhance understanding of the code structure",
291
+ "Focus on areas that haven't been thoroughly traced yet",
292
+ ]
293
+
294
+ def should_call_expert_analysis(self, consolidated_findings, request=None) -> bool:
295
+ """Tracer is self-contained and doesn't need expert analysis."""
296
+ return False
297
+
298
+ def prepare_expert_analysis_context(self, consolidated_findings) -> str:
299
+ """Tracer doesn't use expert analysis."""
300
+ return ""
301
+
302
+ def requires_expert_analysis(self) -> bool:
303
+ """Tracer is self-contained like the planner tool."""
304
+ return False
305
+
306
+ # ================================================================================
307
+ # Workflow Customization - Match Planner Behavior
308
+ # ================================================================================
309
+
310
+ def prepare_step_data(self, request) -> dict:
311
+ """
312
+ Prepare step data from request with tracer-specific fields.
313
+ """
314
+ step_data = {
315
+ "step": request.step,
316
+ "step_number": request.step_number,
317
+ "findings": request.findings,
318
+ "files_checked": request.files_checked,
319
+ "relevant_files": request.relevant_files,
320
+ "relevant_context": request.relevant_context,
321
+ "issues_found": [], # Tracer doesn't track issues
322
+ "confidence": request.confidence or "exploring",
323
+ "hypothesis": None, # Tracer doesn't use hypothesis
324
+ "images": request.images or [],
325
+ # Tracer-specific fields
326
+ "trace_mode": request.trace_mode,
327
+ "target_description": request.target_description,
328
+ }
329
+ return step_data
330
+
331
+ def build_base_response(self, request, continuation_id: str = None) -> dict:
332
+ """
333
+ Build the base response structure with tracer-specific fields.
334
+ """
335
+ # Use work_history from workflow mixin for consistent step tracking
336
+ current_step_count = len(self.work_history) + 1
337
+
338
+ response_data = {
339
+ "status": f"{self.get_name()}_in_progress",
340
+ "step_number": request.step_number,
341
+ "total_steps": request.total_steps,
342
+ "next_step_required": request.next_step_required,
343
+ "step_content": request.step,
344
+ f"{self.get_name()}_status": {
345
+ "files_checked": len(self.consolidated_findings.files_checked),
346
+ "relevant_files": len(self.consolidated_findings.relevant_files),
347
+ "relevant_context": len(self.consolidated_findings.relevant_context),
348
+ "issues_found": len(self.consolidated_findings.issues_found),
349
+ "images_collected": len(self.consolidated_findings.images),
350
+ "current_confidence": self.get_request_confidence(request),
351
+ "step_history_length": current_step_count,
352
+ },
353
+ "metadata": {
354
+ "trace_mode": self.trace_config.get("trace_mode", "unknown"),
355
+ "target_description": self.trace_config.get("target_description", ""),
356
+ "step_history_length": current_step_count,
357
+ },
358
+ }
359
+
360
+ if continuation_id:
361
+ response_data["continuation_id"] = continuation_id
362
+
363
+ return response_data
364
+
365
+ def handle_work_continuation(self, response_data: dict, request) -> dict:
366
+ """
367
+ Handle work continuation with tracer-specific guidance.
368
+ """
369
+ response_data["status"] = f"pause_for_{self.get_name()}"
370
+ response_data[f"{self.get_name()}_required"] = True
371
+
372
+ # Get tracer-specific required actions
373
+ required_actions = self.get_required_actions(
374
+ request.step_number, request.confidence or "exploring", request.findings, request.total_steps
375
+ )
376
+ response_data["required_actions"] = required_actions
377
+
378
+ # Generate step-specific guidance
379
+ if request.step_number == 1:
380
+ # Check if we're in ask mode and need to prompt for mode selection
381
+ if self.get_trace_mode() == "ask":
382
+ response_data["next_steps"] = (
383
+ f"STOP! You MUST ask the user to choose a tracing mode before proceeding. "
384
+ f"Present these options clearly:\\n\\n"
385
+ f"**PRECISION MODE**: Traces execution flow, call chains, and usage patterns. "
386
+ f"Best for understanding how a specific method or function works, what it calls, "
387
+ f"and how data flows through the execution path.\\n\\n"
388
+ f"**DEPENDENCIES MODE**: Maps structural relationships and bidirectional dependencies. "
389
+ f"Best for understanding how a class or module relates to other components, "
390
+ f"what depends on it, and what it depends on.\\n\\n"
391
+ f"After the user selects a mode, call {self.get_name()} again with step_number: 1 "
392
+ f"but with the chosen trace_mode (either 'precision' or 'dependencies')."
393
+ )
394
+ else:
395
+ response_data["next_steps"] = (
396
+ f"MANDATORY: DO NOT call the {self.get_name()} tool again immediately. You MUST first investigate "
397
+ f"the codebase to understand the target code. CRITICAL AWARENESS: You need to find and understand "
398
+ f"the target method/function/class/module, examine its implementation, and begin mapping its "
399
+ f"relationships. Use file reading tools, code search, and systematic examination to gather "
400
+ f"comprehensive information about the target. Only call {self.get_name()} again AFTER completing "
401
+ f"your investigation. When you call {self.get_name()} next time, use step_number: {request.step_number + 1} "
402
+ f"and report specific files examined, code structure discovered, and initial relationship findings."
403
+ )
404
+ elif request.confidence in ["exploring", "low"]:
405
+ next_step = request.step_number + 1
406
+ response_data["next_steps"] = (
407
+ f"STOP! Do NOT call {self.get_name()} again yet. Based on your findings, you've identified areas that need "
408
+ f"deeper tracing analysis. MANDATORY ACTIONS before calling {self.get_name()} step {next_step}:\\n"
409
+ + "\\n".join(f"{i+1}. {action}" for i, action in enumerate(required_actions))
410
+ + f"\\n\\nOnly call {self.get_name()} again with step_number: {next_step} AFTER "
411
+ + "completing these tracing investigations."
412
+ )
413
+ elif request.confidence in ["medium", "high"]:
414
+ next_step = request.step_number + 1
415
+ response_data["next_steps"] = (
416
+ f"WAIT! Your tracing analysis needs final verification. DO NOT call {self.get_name()} immediately. "
417
+ f"REQUIRED ACTIONS:\\n"
418
+ + "\\n".join(f"{i+1}. {action}" for i, action in enumerate(required_actions))
419
+ + f"\\n\\nREMEMBER: Ensure you have traced all significant relationships and execution paths. "
420
+ f"Document findings with specific file references and method signatures, then call {self.get_name()} "
421
+ f"with step_number: {next_step}."
422
+ )
423
+ else:
424
+ # General investigation needed
425
+ next_step = request.step_number + 1
426
+ remaining_steps = request.total_steps - request.step_number
427
+ response_data["next_steps"] = (
428
+ f"Continue systematic tracing with step {next_step}. Approximately {remaining_steps} steps remaining. "
429
+ f"Focus on deepening your understanding of the code relationships and execution patterns."
430
+ )
431
+
432
+ return response_data
433
+
434
+ def customize_workflow_response(self, response_data: dict, request) -> dict:
435
+ """
436
+ Customize response to match tracer tool format with output instructions.
437
+ """
438
+ # Store trace configuration on first step
439
+ if request.step_number == 1:
440
+ self.initial_request = request.step
441
+ self.trace_config = {
442
+ "trace_mode": request.trace_mode,
443
+ "target_description": request.target_description,
444
+ }
445
+
446
+ # Update metadata with trace configuration
447
+ if "metadata" in response_data:
448
+ response_data["metadata"]["trace_mode"] = request.trace_mode or "unknown"
449
+ response_data["metadata"]["target_description"] = request.target_description or ""
450
+
451
+ # If in ask mode, mark this as mode selection phase
452
+ if request.trace_mode == "ask":
453
+ response_data["mode_selection_required"] = True
454
+ response_data["status"] = "mode_selection_required"
455
+
456
+ # Add tracer-specific output instructions for final steps
457
+ if not request.next_step_required:
458
+ response_data["tracing_complete"] = True
459
+ response_data["trace_summary"] = f"TRACING COMPLETE: {request.step}"
460
+
461
+ # Get mode-specific output instructions
462
+ trace_mode = self.trace_config.get("trace_mode", "precision")
463
+ rendering_instructions = self._get_rendering_instructions(trace_mode)
464
+
465
+ response_data["output"] = {
466
+ "instructions": (
467
+ "This is a structured tracing analysis response. Present the comprehensive tracing findings "
468
+ "using the specific rendering format for the trace mode. Follow the exact formatting guidelines "
469
+ "provided in rendering_instructions. Include all discovered relationships, execution paths, "
470
+ "and dependencies with precise file references and line numbers."
471
+ ),
472
+ "format": f"{trace_mode}_trace_analysis",
473
+ "rendering_instructions": rendering_instructions,
474
+ "presentation_guidelines": {
475
+ "completed_trace": (
476
+ "Use the exact rendering format specified for the trace mode. Include comprehensive "
477
+ "diagrams, tables, and structured analysis. Reference specific file paths and line numbers. "
478
+ "Follow formatting rules precisely."
479
+ ),
480
+ "step_content": "Present as main analysis with clear structure and actionable insights.",
481
+ "continuation": "Use continuation_id for related tracing sessions or follow-up analysis",
482
+ },
483
+ }
484
+ response_data["next_steps"] = (
485
+ f"Tracing analysis complete. Present the comprehensive {trace_mode} trace analysis to the user "
486
+ f"using the exact rendering format specified in the output instructions. Follow the formatting "
487
+ f"guidelines precisely, including diagrams, tables, and file references. After presenting the "
488
+ f"analysis, offer to help with related tracing tasks or use the continuation_id for follow-up analysis."
489
+ )
490
+
491
+ # Convert generic status names to tracer-specific ones
492
+ tool_name = self.get_name()
493
+ status_mapping = {
494
+ f"{tool_name}_in_progress": "tracing_in_progress",
495
+ f"pause_for_{tool_name}": "pause_for_tracing",
496
+ f"{tool_name}_required": "tracing_required",
497
+ f"{tool_name}_complete": "tracing_complete",
498
+ }
499
+
500
+ if response_data["status"] in status_mapping:
501
+ response_data["status"] = status_mapping[response_data["status"]]
502
+
503
+ return response_data
504
+
505
+ def _get_rendering_instructions(self, trace_mode: str) -> str:
506
+ """
507
+ Get mode-specific rendering instructions for the CLI agent.
508
+
509
+ Args:
510
+ trace_mode: Either "precision" or "dependencies"
511
+
512
+ Returns:
513
+ str: Complete rendering instructions for the specified mode
514
+ """
515
+ if trace_mode == "precision":
516
+ return self._get_precision_rendering_instructions()
517
+ else: # dependencies mode
518
+ return self._get_dependencies_rendering_instructions()
519
+
520
+ def _get_precision_rendering_instructions(self) -> str:
521
+ """Get rendering instructions for precision trace mode."""
522
+ return """
523
+ ## MANDATORY RENDERING INSTRUCTIONS FOR PRECISION TRACE
524
+
525
+ You MUST render the trace analysis using ONLY the Vertical Indented Flow Style:
526
+
527
+ ### CALL FLOW DIAGRAM - Vertical Indented Style
528
+
529
+ **EXACT FORMAT TO FOLLOW:**
530
+ ```
531
+ [ClassName::MethodName] (file: /complete/file/path.ext, line: ##)
532
+ ↓
533
+ [AnotherClass::calledMethod] (file: /path/to/file.ext, line: ##)
534
+ ↓
535
+ [ThirdClass::nestedMethod] (file: /path/file.ext, line: ##)
536
+ ↓
537
+ [DeeperClass::innerCall] (file: /path/inner.ext, line: ##) ? if some_condition
538
+ ↓
539
+ [ServiceClass::processData] (file: /services/service.ext, line: ##)
540
+ ↓
541
+ [RepositoryClass::saveData] (file: /data/repo.ext, line: ##)
542
+ ↓
543
+ [ClientClass::sendRequest] (file: /clients/client.ext, line: ##)
544
+ ↓
545
+ [EmailService::sendEmail] (file: /email/service.ext, line: ##) ⚠️ ambiguous branch
546
+ →
547
+ [SMSService::sendSMS] (file: /sms/service.ext, line: ##) ⚠️ ambiguous branch
548
+ ```
549
+
550
+ **CRITICAL FORMATTING RULES:**
551
+
552
+ 1. **Method Names**: Use the actual naming convention of the project language you're analyzing. Automatically detect and adapt to the project's conventions (camelCase, snake_case, PascalCase, etc.) based on the codebase structure and file extensions.
553
+
554
+ 2. **Vertical Flow Arrows**:
555
+ - Use `↓` for standard sequential calls (vertical flow)
556
+ - Use `→` for parallel/alternative calls (horizontal branch)
557
+ - NEVER use other arrow types
558
+
559
+ 3. **Indentation Logic**:
560
+ - Start at column 0 for entry point
561
+ - Indent 2 spaces for each nesting level
562
+ - Maintain consistent indentation for same call depth
563
+ - Sibling calls at same level should have same indentation
564
+
565
+ 4. **Conditional Calls**:
566
+ - Add `? if condition_description` after method for conditional execution
567
+ - Use actual condition names from code when possible
568
+
569
+ 5. **Ambiguous Branches**:
570
+ - Mark with `⚠️ ambiguous branch` when execution path is uncertain
571
+ - Use `→` to show alternative paths at same indentation level
572
+
573
+ 6. **File Path Format**:
574
+ - Use complete relative paths from project root
575
+ - Include actual file extensions from the project
576
+ - Show exact line numbers where method is defined
577
+
578
+ ### ADDITIONAL ANALYSIS VIEWS
579
+
580
+ **1. BRANCHING & SIDE EFFECT TABLE**
581
+
582
+ | Location | Condition | Branches | Uncertain |
583
+ |----------|-----------|----------|-----------|
584
+ | CompleteFileName.ext:## | if actual_condition_from_code | method1(), method2(), else skip | No |
585
+ | AnotherFile.ext:## | if boolean_check | callMethod(), else return | No |
586
+ | ThirdFile.ext:## | if validation_passes | processData(), else throw | Yes |
587
+
588
+ **2. SIDE EFFECTS**
589
+ ```
590
+ Side Effects:
591
+ - [database] Specific database operation description (CompleteFileName.ext:##)
592
+ - [network] Specific network call description (CompleteFileName.ext:##)
593
+ - [filesystem] Specific file operation description (CompleteFileName.ext:##)
594
+ - [state] State changes or property modifications (CompleteFileName.ext:##)
595
+ - [memory] Memory allocation or cache operations (CompleteFileName.ext:##)
596
+ ```
597
+
598
+ **3. USAGE POINTS**
599
+ ```
600
+ Usage Points:
601
+ 1. FileName.ext:## - Context description of where/why it's called
602
+ 2. AnotherFile.ext:## - Context description of usage scenario
603
+ 3. ThirdFile.ext:## - Context description of calling pattern
604
+ 4. FourthFile.ext:## - Context description of integration point
605
+ ```
606
+
607
+ **4. ENTRY POINTS**
608
+ ```
609
+ Entry Points:
610
+ - ClassName::methodName (context: where this flow typically starts)
611
+ - AnotherClass::entryMethod (context: alternative entry scenario)
612
+ - ThirdClass::triggerMethod (context: event-driven entry point)
613
+ ```
614
+
615
+ **ABSOLUTE REQUIREMENTS:**
616
+ - Use ONLY the vertical indented style for the call flow diagram
617
+ - Present ALL FOUR additional analysis views (Branching Table, Side Effects, Usage Points, Entry Points)
618
+ - Adapt method naming to match the project's programming language conventions
619
+ - Use exact file paths and line numbers from the actual codebase
620
+ - DO NOT invent or guess method names or locations
621
+ - Follow indentation rules precisely for call hierarchy
622
+ - Mark uncertain execution paths clearly
623
+ - Provide contextual descriptions in Usage Points and Entry Points sections
624
+ - Include comprehensive side effects categorization (database, network, filesystem, state, memory)"""
625
+
626
+ def _get_dependencies_rendering_instructions(self) -> str:
627
+ """Get rendering instructions for dependencies trace mode."""
628
+ return """
629
+ ## MANDATORY RENDERING INSTRUCTIONS FOR DEPENDENCIES TRACE
630
+
631
+ You MUST render the trace analysis using ONLY the Bidirectional Arrow Flow Style:
632
+
633
+ ### DEPENDENCY FLOW DIAGRAM - Bidirectional Arrow Style
634
+
635
+ **EXACT FORMAT TO FOLLOW:**
636
+ ```
637
+ INCOMING DEPENDENCIES → [TARGET_CLASS/MODULE] → OUTGOING DEPENDENCIES
638
+
639
+ CallerClass::callerMethod ←────┐
640
+ AnotherCaller::anotherMethod ←─┤
641
+ ThirdCaller::thirdMethod ←─────┤
642
+ │
643
+ [TARGET_CLASS/MODULE]
644
+ │
645
+ ├────→ FirstDependency::method
646
+ ├────→ SecondDependency::method
647
+ └────→ ThirdDependency::method
648
+
649
+ TYPE RELATIONSHIPS:
650
+ InterfaceName ──implements──→ [TARGET_CLASS] ──extends──→ BaseClass
651
+ DTOClass ──uses──→ [TARGET_CLASS] ──uses──→ EntityClass
652
+ ```
653
+
654
+ **CRITICAL FORMATTING RULES:**
655
+
656
+ 1. **Target Placement**: Always place the target class/module in square brackets `[TARGET_NAME]` at the center
657
+ 2. **Incoming Dependencies**: Show on the left side with `←` arrows pointing INTO the target
658
+ 3. **Outgoing Dependencies**: Show on the right side with `→` arrows pointing OUT FROM the target
659
+ 4. **Arrow Alignment**: Use consistent spacing and alignment for visual clarity
660
+ 5. **Method Naming**: Use the project's actual naming conventions detected from the codebase
661
+ 6. **File References**: Include complete file paths and line numbers
662
+
663
+ **VISUAL LAYOUT RULES:**
664
+
665
+ 1. **Header Format**: Always start with the flow direction indicator
666
+ 2. **Left Side (Incoming)**:
667
+ - List all callers with `←` arrows
668
+ - Use `┐`, `┤`, `┘` box drawing characters for clean connection lines
669
+ - Align arrows consistently
670
+
671
+ 3. **Center (Target)**:
672
+ - Enclose target in square brackets
673
+ - Position centrally between incoming and outgoing
674
+
675
+ 4. **Right Side (Outgoing)**:
676
+ - List all dependencies with `→` arrows
677
+ - Use `├`, `└` box drawing characters for branching
678
+ - Maintain consistent spacing
679
+
680
+ 5. **Type Relationships Section**:
681
+ - Use `──relationship──→` format with double hyphens
682
+ - Show inheritance, implementation, and usage relationships
683
+ - Place below the main flow diagram
684
+
685
+ **DEPENDENCY TABLE:**
686
+
687
+ | Type | From/To | Method | File | Line |
688
+ |------|---------|--------|------|------|
689
+ | incoming_call | From: CallerClass | callerMethod | /complete/path/file.ext | ## |
690
+ | outgoing_call | To: TargetClass | targetMethod | /complete/path/file.ext | ## |
691
+ | implements | Self: ThisClass | — | /complete/path/file.ext | — |
692
+ | extends | Self: ThisClass | — | /complete/path/file.ext | — |
693
+ | uses_type | Self: ThisClass | — | /complete/path/file.ext | — |
694
+
695
+ **ABSOLUTE REQUIREMENTS:**
696
+ - Use ONLY the bidirectional arrow flow style shown above
697
+ - Automatically detect and use the project's naming conventions
698
+ - Use exact file paths and line numbers from the actual codebase
699
+ - DO NOT invent or guess method/class names
700
+ - Maintain visual alignment and consistent spacing
701
+ - Include type relationships section when applicable
702
+ - Show clear directional flow with proper arrows"""
703
+
704
+ # ================================================================================
705
+ # Hook Method Overrides for Tracer-Specific Behavior
706
+ # ================================================================================
707
+
708
+ def get_completion_status(self) -> str:
709
+ """Tracer uses tracing-specific status."""
710
+ return "tracing_complete"
711
+
712
+ def get_completion_data_key(self) -> str:
713
+ """Tracer uses 'complete_tracing' key."""
714
+ return "complete_tracing"
715
+
716
+ def get_completion_message(self) -> str:
717
+ """Tracer-specific completion message."""
718
+ return (
719
+ "Tracing analysis complete. Present the comprehensive trace analysis to the user "
720
+ "using the specified rendering format and offer to help with related tracing tasks."
721
+ )
722
+
723
+ def get_skip_reason(self) -> str:
724
+ """Tracer-specific skip reason."""
725
+ return "Tracer is self-contained and completes analysis without external assistance"
726
+
727
+ def get_skip_expert_analysis_status(self) -> str:
728
+ """Tracer-specific expert analysis skip status."""
729
+ return "skipped_by_tool_design"
730
+
731
+ def store_initial_issue(self, step_description: str):
732
+ """Store initial tracing description."""
733
+ self.initial_tracing_description = step_description
734
+
735
+ def get_initial_request(self, fallback_step: str) -> str:
736
+ """Get initial tracing description."""
737
+ try:
738
+ return self.initial_tracing_description
739
+ except AttributeError:
740
+ return fallback_step
741
+
742
+ def get_request_confidence(self, request) -> str:
743
+ """Get confidence from request for tracer workflow."""
744
+ try:
745
+ return request.confidence or "exploring"
746
+ except AttributeError:
747
+ return "exploring"
748
+
749
+ def get_trace_mode(self) -> str:
750
+ """Get current trace mode. Override for custom trace mode handling."""
751
+ try:
752
+ return self.trace_config.get("trace_mode", "ask")
753
+ except AttributeError:
754
+ return "ask"
755
+
756
+ # Required abstract methods from BaseTool
757
+ def get_request_model(self):
758
+ """Return the tracer-specific request model."""
759
+ return TracerRequest
760
+
761
+ async def prepare_prompt(self, request) -> str:
762
+ """Not used - workflow tools use execute_workflow()."""
763
+ return "" # Workflow tools use execute_workflow() directly