x-ipe 1.0.23__py3-none-any.whl → 1.0.25__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 (146) hide show
  1. x_ipe/app.py +32 -1
  2. x_ipe/handlers/terminal_handlers.py +6 -0
  3. x_ipe/handlers/voice_handlers.py +5 -0
  4. x_ipe/resources/copilot-instructions.md +19 -6
  5. x_ipe/resources/skills/lesson-learned/SKILL.md +208 -0
  6. x_ipe/resources/skills/lesson-learned/references/examples.md +238 -0
  7. x_ipe/resources/skills/project-quality-board-management/SKILL.md +135 -298
  8. x_ipe/resources/skills/project-quality-board-management/references/evaluation-principles.md +213 -0
  9. x_ipe/resources/skills/project-quality-board-management/references/evaluation-procedures.md +214 -0
  10. x_ipe/resources/skills/project-quality-board-management/templates/quality-report.md +70 -18
  11. x_ipe/resources/skills/task-execution-guideline/SKILL.md +2 -2
  12. x_ipe/resources/skills/task-execution-guideline/templates/task-record.yaml +1 -1
  13. x_ipe/resources/skills/task-type-code-implementation/SKILL.md +72 -270
  14. x_ipe/resources/skills/task-type-code-implementation/references/implementation-guidelines.md +432 -0
  15. x_ipe/resources/skills/task-type-code-refactor-v2/SKILL.md +127 -353
  16. x_ipe/resources/skills/task-type-code-refactor-v2/references/refactoring-techniques.md +373 -0
  17. x_ipe/resources/skills/task-type-feature-breakdown/SKILL.md +31 -243
  18. x_ipe/resources/skills/task-type-feature-breakdown/references/breakdown-guidelines.md +330 -0
  19. x_ipe/resources/skills/task-type-feature-refinement/SKILL.md +27 -180
  20. x_ipe/resources/skills/task-type-feature-refinement/references/specification-writing-guide.md +267 -0
  21. x_ipe/resources/skills/task-type-idea-mockup/SKILL.md +38 -276
  22. x_ipe/resources/skills/task-type-idea-mockup/references/mockup-guidelines.md +299 -0
  23. x_ipe/resources/skills/task-type-idea-to-architecture/SKILL.md +20 -218
  24. x_ipe/resources/skills/task-type-idea-to-architecture/references/architecture-patterns.md +342 -0
  25. x_ipe/resources/skills/task-type-ideation/SKILL.md +10 -266
  26. x_ipe/resources/skills/task-type-ideation/references/folder-naming-guide.md +55 -0
  27. x_ipe/resources/skills/task-type-ideation/references/tool-usage-guide.md +236 -0
  28. x_ipe/resources/skills/task-type-ideation-v2/SKILL.md +488 -0
  29. x_ipe/resources/skills/task-type-ideation-v2/references/examples.md +377 -0
  30. x_ipe/resources/skills/task-type-ideation-v2/references/folder-naming-guide.md +74 -0
  31. x_ipe/resources/skills/task-type-ideation-v2/references/tool-usage-guide.md +145 -0
  32. x_ipe/resources/skills/task-type-ideation-v2/references/visualization-guide.md +160 -0
  33. x_ipe/resources/skills/task-type-ideation-v2/templates/idea-summary.md +86 -0
  34. x_ipe/resources/skills/task-type-refactoring-analysis/SKILL.md +83 -145
  35. x_ipe/resources/skills/task-type-refactoring-analysis/references/output-schema.md +172 -0
  36. x_ipe/resources/skills/task-type-technical-design/SKILL.md +28 -214
  37. x_ipe/resources/skills/task-type-technical-design/references/design-templates.md +422 -0
  38. x_ipe/resources/skills/task-type-test-generation/SKILL.md +47 -332
  39. x_ipe/resources/skills/task-type-test-generation/references/test-patterns.md +368 -0
  40. x_ipe/resources/skills/tool-tracing-creator/SKILL.md +312 -0
  41. x_ipe/resources/skills/tool-tracing-creator/references/examples.md +324 -0
  42. x_ipe/resources/skills/tool-tracing-instrumentation/SKILL.md +373 -0
  43. x_ipe/resources/skills/tool-tracing-instrumentation/references/examples.md +264 -0
  44. x_ipe/resources/skills/x-ipe-skill-creator-v3/SKILL.md +486 -0
  45. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/10. example-gate-conditions.md +73 -0
  46. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/11. reference-quality-standards.md +127 -0
  47. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/2. reference-section-order.md +127 -0
  48. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/3. example-step-based-code-review.md +84 -0
  49. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/4. example-step-based-feature-implementation.md +113 -0
  50. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/5. example-function-based-validation.md +73 -0
  51. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/6. example-function-based-analysis.md +94 -0
  52. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/7. example-task-io-code-implementation.md +36 -0
  53. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/8. example-structured-summary.md +43 -0
  54. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/9. example-dor-dod.md +77 -0
  55. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/examples.md +429 -0
  56. x_ipe/resources/skills/x-ipe-skill-creator-v3/references/skill-general-guidelines-v2.md +611 -0
  57. x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-meta.md +153 -0
  58. x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-task-based.md +324 -0
  59. x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-task-category.md +109 -0
  60. x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-tool.md +205 -0
  61. x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-meta.md +334 -0
  62. x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-task-based.md +279 -0
  63. x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-tool.md +175 -0
  64. x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-workflow-orchestration.md +329 -0
  65. x_ipe/resources/skills/x-ipe-task-based-ideation/SKILL.md +487 -0
  66. x_ipe/resources/skills/x-ipe-task-based-ideation/references/examples.md +377 -0
  67. x_ipe/resources/skills/x-ipe-task-based-ideation/references/folder-naming-guide.md +74 -0
  68. x_ipe/resources/skills/x-ipe-task-based-ideation/references/tool-usage-guide.md +145 -0
  69. x_ipe/resources/skills/x-ipe-task-based-ideation/references/visualization-guide.md +160 -0
  70. x_ipe/resources/skills/x-ipe-task-based-ideation/templates/idea-summary.md +86 -0
  71. x_ipe/routes/__init__.py +2 -0
  72. x_ipe/routes/ideas_routes.py +289 -0
  73. x_ipe/routes/kb_routes.py +80 -0
  74. x_ipe/routes/main_routes.py +18 -0
  75. x_ipe/routes/project_routes.py +7 -0
  76. x_ipe/routes/proxy_routes.py +10 -2
  77. x_ipe/routes/quality_evaluation_routes.py +193 -0
  78. x_ipe/routes/settings_routes.py +6 -0
  79. x_ipe/routes/tools_routes.py +6 -0
  80. x_ipe/routes/tracing_routes.py +232 -0
  81. x_ipe/routes/uiux_feedback_routes.py +50 -0
  82. x_ipe/services/__init__.py +5 -0
  83. x_ipe/services/config_service.py +6 -0
  84. x_ipe/services/file_service.py +20 -0
  85. x_ipe/services/homepage_service.py +160 -0
  86. x_ipe/services/ideas_service.py +535 -2
  87. x_ipe/services/kb_service.py +378 -0
  88. x_ipe/services/proxy_service.py +37 -7
  89. x_ipe/services/settings_service.py +13 -0
  90. x_ipe/services/skills_service.py +4 -0
  91. x_ipe/services/terminal_service.py +24 -0
  92. x_ipe/services/themes_service.py +4 -0
  93. x_ipe/services/tools_config_service.py +4 -0
  94. x_ipe/services/tracing_service.py +333 -0
  95. x_ipe/services/uiux_feedback_service.py +148 -1
  96. x_ipe/services/voice_input_service_v2.py +11 -0
  97. x_ipe/static/css/base.css +7 -0
  98. x_ipe/static/css/homepage-infinity.css +330 -0
  99. x_ipe/static/css/kb-core.css +301 -0
  100. x_ipe/static/css/quality-evaluation.css +345 -0
  101. x_ipe/static/css/sidebar.css +14 -4
  102. x_ipe/static/css/terminal.css +23 -0
  103. x_ipe/static/css/tracing-dashboard.css +796 -0
  104. x_ipe/static/css/uiux-feedback.css +7 -1
  105. x_ipe/static/css/workplace.css +636 -0
  106. x_ipe/static/img/homepage-infinity-loop.png +0 -0
  107. x_ipe/static/js/features/confirm-dialog.js +169 -0
  108. x_ipe/static/js/features/folder-view.js +742 -0
  109. x_ipe/static/js/features/homepage-infinity.js +314 -0
  110. x_ipe/static/js/features/kb-core.js +371 -0
  111. x_ipe/static/js/features/quality-evaluation.js +387 -0
  112. x_ipe/static/js/features/sidebar.js +255 -12
  113. x_ipe/static/js/features/tracing-dashboard.js +855 -0
  114. x_ipe/static/js/features/tracing-graph.js +1031 -0
  115. x_ipe/static/js/features/tree-drag.js +227 -0
  116. x_ipe/static/js/features/tree-search.js +228 -0
  117. x_ipe/static/js/features/workplace.js +661 -33
  118. x_ipe/static/js/init.js +76 -0
  119. x_ipe/static/js/terminal-v2.js +45 -14
  120. x_ipe/static/js/terminal.js +50 -49
  121. x_ipe/static/js/uiux-feedback.js +75 -16
  122. x_ipe/templates/base.html +24 -0
  123. x_ipe/templates/index.html +10 -1
  124. x_ipe/templates/knowledge-base.html +110 -0
  125. x_ipe/templates/workplace.html +4 -0
  126. x_ipe/tracing/__init__.py +37 -0
  127. x_ipe/tracing/buffer.py +135 -0
  128. x_ipe/tracing/context.py +125 -0
  129. x_ipe/tracing/decorator.py +288 -0
  130. x_ipe/tracing/middleware.py +197 -0
  131. x_ipe/tracing/parser.py +235 -0
  132. x_ipe/tracing/redactor.py +111 -0
  133. x_ipe/tracing/writer.py +122 -0
  134. {x_ipe-1.0.23.dist-info → x_ipe-1.0.25.dist-info}/METADATA +2 -2
  135. {x_ipe-1.0.23.dist-info → x_ipe-1.0.25.dist-info}/RECORD +138 -65
  136. x_ipe/app.py.bak +0 -1333
  137. x_ipe/resources/skills/x-ipe-skill-creator/SKILL.md +0 -329
  138. x_ipe/resources/skills/x-ipe-skill-creator/references/output-patterns.md +0 -169
  139. x_ipe/resources/skills/x-ipe-skill-creator/references/skill-structure.md +0 -162
  140. x_ipe/resources/skills/x-ipe-skill-creator/references/workflows.md +0 -110
  141. x_ipe/resources/skills/x-ipe-skill-creator/templates/references/examples.md +0 -113
  142. x_ipe/resources/skills/x-ipe-skill-creator/templates/skill-category-skill.md +0 -296
  143. x_ipe/resources/skills/x-ipe-skill-creator/templates/task-type-skill.md +0 -269
  144. {x_ipe-1.0.23.dist-info → x_ipe-1.0.25.dist-info}/WHEEL +0 -0
  145. {x_ipe-1.0.23.dist-info → x_ipe-1.0.25.dist-info}/entry_points.txt +0 -0
  146. {x_ipe-1.0.23.dist-info → x_ipe-1.0.25.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,110 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Knowledge Base - X-IPE{% endblock %}
4
+
5
+ {% block body %}
6
+ <div class="app-container">
7
+ <!-- ROW 1: Top Bar -->
8
+ <header class="top-bar">
9
+ <div class="d-flex align-items-center gap-3">
10
+ <a href="/" class="top-bar-brand text-decoration-none">
11
+ <i class="bi bi-journal-code me-2"></i>X-IPE
12
+ </a>
13
+ <nav aria-label="breadcrumb" class="top-bar-breadcrumb">
14
+ <ol class="breadcrumb mb-0" id="breadcrumb">
15
+ <li class="breadcrumb-item active">Knowledge Base</li>
16
+ </ol>
17
+ </nav>
18
+ </div>
19
+ <div class="d-flex align-items-center gap-2">
20
+ <button class="btn btn-sm btn-primary" id="btn-refresh-index" title="Refresh index">
21
+ <i class="bi bi-arrow-clockwise"></i> Refresh
22
+ </button>
23
+ <a href="/settings" class="btn btn-link text-light" title="Settings">
24
+ <i class="bi bi-gear-fill"></i>
25
+ </a>
26
+ </div>
27
+ </header>
28
+
29
+ <!-- ROW 2: Middle Section (sidebar + content) -->
30
+ <div class="middle-section" id="middle-section">
31
+ <!-- LEFT: Sidebar Navigation -->
32
+ <nav class="sidebar" id="sidebar">
33
+ <!-- Search Box -->
34
+ <div class="kb-sidebar-search p-2">
35
+ <input type="text" class="form-control form-control-sm" id="kb-search"
36
+ placeholder="Search files..." aria-label="Search knowledge base">
37
+ </div>
38
+ <!-- File Tree -->
39
+ <div class="sidebar-content" id="sidebar-content">
40
+ <div class="loading-spinner">
41
+ <div class="spinner-border spinner-border-sm text-light" role="status">
42
+ <span class="visually-hidden">Loading...</span>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </nav>
47
+
48
+ <!-- Resize Handle -->
49
+ <div class="sidebar-resize-handle" id="sidebar-resize-handle"></div>
50
+
51
+ <!-- RIGHT: Content Area -->
52
+ <main class="content-area">
53
+ <div class="content-view" id="content-view">
54
+ <div class="content-header d-flex justify-content-between align-items-center" id="content-header">
55
+ <h5 class="mb-0" id="content-title">Knowledge Base</h5>
56
+ <div class="kb-stats" id="kb-stats">
57
+ <!-- File count, topic count loaded here -->
58
+ </div>
59
+ </div>
60
+ <div class="content-body" id="content-body">
61
+ <!-- KB content loaded here -->
62
+ <div class="kb-landing-view" id="kb-landing-view">
63
+ <div class="kb-section">
64
+ <h6><i class="bi bi-inbox me-2"></i>Landing (Unprocessed)</h6>
65
+ <div class="kb-file-list" id="landing-files">
66
+ <p class="text-muted small">No files in landing folder</p>
67
+ </div>
68
+ </div>
69
+ <div class="kb-section mt-4">
70
+ <h6><i class="bi bi-folder me-2"></i>Topics</h6>
71
+ <div class="kb-topics-grid" id="topics-grid">
72
+ <p class="text-muted small">No topics created yet</p>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ </main>
79
+ </div>
80
+
81
+ <!-- ROW 3: Footer Terminal Panel -->
82
+ <div class="terminal-panel" id="terminal-panel">
83
+ <div class="terminal-header">
84
+ <div class="terminal-tabs" id="terminal-tabs">
85
+ <!-- Tabs rendered by JavaScript -->
86
+ </div>
87
+ <div class="d-flex align-items-center gap-2">
88
+ <button class="btn btn-sm btn-outline-light" id="btn-new-terminal" title="New Terminal">
89
+ <i class="bi bi-plus"></i>
90
+ </button>
91
+ <button class="btn btn-sm btn-outline-light terminal-toggle" id="terminal-toggle" title="Toggle Terminal">
92
+ <i class="bi bi-chevron-down"></i>
93
+ </button>
94
+ </div>
95
+ </div>
96
+ <div class="terminal-body" id="terminal-body">
97
+ <!-- xterm.js terminals rendered here -->
98
+ </div>
99
+ </div>
100
+ </div>
101
+
102
+ <script>
103
+ // Auto-initialize KB view when page loads
104
+ document.addEventListener('DOMContentLoaded', function() {
105
+ if (window.kbCore) {
106
+ window.kbCore.init();
107
+ }
108
+ });
109
+ </script>
110
+ {% endblock %}
@@ -21,6 +21,10 @@
21
21
  <button class="btn btn-sm btn-primary" id="btn-create-idea" title="Create new idea">
22
22
  <i class="bi bi-plus-lg"></i> Create Idea
23
23
  </button>
24
+ <!-- FEATURE-025-A: Knowledge Base Button -->
25
+ <button class="btn btn-sm btn-outline-secondary" id="btn-knowledge-base" title="Knowledge Base">
26
+ <i class="bi bi-archive"></i>
27
+ </button>
24
28
  <!-- FEATURE-011: Stage Toolbox Button -->
25
29
  <button class="btn btn-sm btn-outline-secondary" id="btn-stage-toolbox" title="Stage Toolbox">
26
30
  <i class="bi bi-tools"></i>
@@ -0,0 +1,37 @@
1
+ """
2
+ FEATURE-023: Application Action Tracing - Core
3
+
4
+ Tracing module for X-IPE applications.
5
+
6
+ Provides automatic function tracing with sensitive data redaction,
7
+ execution timing, and structured log output.
8
+
9
+ Usage:
10
+ from x_ipe.tracing import x_ipe_tracing, TraceContext
11
+
12
+ @x_ipe_tracing(level="INFO", redact=["password"])
13
+ def my_function(email: str, password: str):
14
+ ...
15
+
16
+ # Start/end traces manually (usually done by middleware)
17
+ TraceContext.start_trace("POST /api/endpoint")
18
+ # ... execute traced functions ...
19
+ buffer = TraceContext.end_trace()
20
+ """
21
+
22
+ from .decorator import x_ipe_tracing
23
+ from .context import TraceContext
24
+ from .buffer import TraceBuffer, TraceEntry
25
+ from .writer import TraceLogWriter
26
+ from .redactor import Redactor
27
+ from .middleware import init_tracing_middleware
28
+
29
+ __all__ = [
30
+ 'x_ipe_tracing',
31
+ 'TraceContext',
32
+ 'TraceBuffer',
33
+ 'TraceEntry',
34
+ 'TraceLogWriter',
35
+ 'Redactor',
36
+ 'init_tracing_middleware',
37
+ ]
@@ -0,0 +1,135 @@
1
+ """
2
+ FEATURE-023: Application Action Tracing - Core
3
+
4
+ TraceBuffer and TraceEntry for in-memory trace storage.
5
+
6
+ Traces are collected in-memory during request execution and flushed
7
+ to log files upon request completion.
8
+ """
9
+ from dataclasses import dataclass, field
10
+ from datetime import datetime, timezone
11
+ from typing import List, Optional, Any
12
+ import json
13
+
14
+
15
+ @dataclass
16
+ class TraceEntry:
17
+ """
18
+ Single trace log entry representing a function call event.
19
+
20
+ Attributes:
21
+ timestamp: When the event occurred
22
+ trace_id: Unique identifier for the trace
23
+ level: Log level (INFO, DEBUG, ERROR)
24
+ direction: Arrow direction (→ for entry, ← for exit)
25
+ event_type: Type of event (start_function, return_function, exception)
26
+ function_name: Name of the traced function
27
+ data: Parameters, return value, or error details
28
+ duration_ms: Execution time in milliseconds (only for exit events)
29
+ depth: Nesting level (0 = root)
30
+ """
31
+ timestamp: datetime
32
+ trace_id: str
33
+ level: str
34
+ direction: str
35
+ event_type: str
36
+ function_name: str
37
+ data: dict
38
+ duration_ms: Optional[float] = None
39
+ depth: int = 0
40
+
41
+
42
+ class TraceBuffer:
43
+ """
44
+ In-memory buffer for trace entries during request execution.
45
+
46
+ Collects trace entries and formats them for log file output.
47
+ Enforces a maximum size limit to prevent memory exhaustion.
48
+
49
+ Usage:
50
+ buffer = TraceBuffer("abc-123", "POST /api/orders")
51
+ buffer.add(TraceEntry(...))
52
+ log_content = buffer.to_log_string("SUCCESS", 150.0)
53
+ """
54
+
55
+ MAX_SIZE = 10 * 1024 * 1024 # 10MB limit
56
+
57
+ def __init__(self, trace_id: str, root_api: str):
58
+ """
59
+ Initialize TraceBuffer.
60
+
61
+ Args:
62
+ trace_id: Unique identifier for this trace
63
+ root_api: The root API call (e.g., "POST /api/orders")
64
+ """
65
+ self.trace_id = trace_id
66
+ self.root_api = root_api
67
+ self.started_at = datetime.now(timezone.utc)
68
+ self.entries: List[TraceEntry] = []
69
+ self._size = 0
70
+
71
+ def add(self, entry: TraceEntry) -> None:
72
+ """
73
+ Add a trace entry to the buffer.
74
+
75
+ Silently drops entries if buffer size limit is exceeded.
76
+
77
+ Args:
78
+ entry: TraceEntry to add
79
+ """
80
+ try:
81
+ entry_size = len(json.dumps(entry.data, default=str))
82
+ except (TypeError, ValueError):
83
+ entry_size = 100 # Fallback size estimate
84
+
85
+ if self._size + entry_size > self.MAX_SIZE:
86
+ return # Silently drop if buffer full
87
+
88
+ self.entries.append(entry)
89
+ self._size += entry_size
90
+
91
+ def to_log_string(self, status: str, total_ms: float) -> str:
92
+ """
93
+ Format the buffer as a log file string.
94
+
95
+ Args:
96
+ status: Final status (SUCCESS, ERROR)
97
+ total_ms: Total execution time in milliseconds
98
+
99
+ Returns:
100
+ Formatted log string ready for file output
101
+ """
102
+ lines = [
103
+ f"[TRACE-START] {self.trace_id} | {self.root_api} | {self.started_at.isoformat()}Z"
104
+ ]
105
+
106
+ for entry in self.entries:
107
+ indent = " " * (entry.depth + 1)
108
+
109
+ try:
110
+ data_str = json.dumps(entry.data, default=str, ensure_ascii=False)
111
+ except (TypeError, ValueError):
112
+ data_str = str(entry.data)
113
+
114
+ # Truncate very long data
115
+ if len(data_str) > 1000:
116
+ data_str = data_str[:997] + "..."
117
+
118
+ if entry.duration_ms is not None:
119
+ line = (
120
+ f"{indent}[{entry.level}] {entry.direction} {entry.event_type}: "
121
+ f"{entry.function_name} | {data_str} | {entry.duration_ms:.0f}ms"
122
+ )
123
+ else:
124
+ line = (
125
+ f"{indent}[{entry.level}] {entry.direction} {entry.event_type}: "
126
+ f"{entry.function_name} | {data_str}"
127
+ )
128
+
129
+ lines.append(line)
130
+
131
+ lines.append(
132
+ f"[TRACE-END] {self.trace_id} | {total_ms:.0f}ms | {status}"
133
+ )
134
+
135
+ return "\n".join(lines)
@@ -0,0 +1,125 @@
1
+ """
2
+ FEATURE-023: Application Action Tracing - Core
3
+
4
+ TraceContext for thread-safe context propagation using contextvars.
5
+
6
+ Manages the active trace context across nested function calls,
7
+ ensuring trace ID propagation and proper nesting depth tracking.
8
+ """
9
+ from contextvars import ContextVar
10
+ from typing import Optional, List
11
+ import uuid
12
+
13
+ from .buffer import TraceBuffer
14
+
15
+
16
+ # Thread-safe context variable for the active trace
17
+ _trace_context: ContextVar[Optional['TraceContext']] = ContextVar(
18
+ 'trace_context',
19
+ default=None
20
+ )
21
+
22
+
23
+ class TraceContext:
24
+ """
25
+ Thread-safe trace context manager.
26
+
27
+ Uses Python's contextvars to maintain trace state across async
28
+ function calls. Tracks trace ID, buffer, and call depth.
29
+
30
+ Usage:
31
+ # Start a new trace
32
+ ctx = TraceContext.start_trace("POST /api/orders")
33
+
34
+ # Get current context (in nested calls)
35
+ ctx = TraceContext.get_current()
36
+
37
+ # End trace and get buffer
38
+ buffer = TraceContext.end_trace()
39
+ """
40
+
41
+ def __init__(self, trace_id: str, root_api: str):
42
+ """
43
+ Initialize TraceContext.
44
+
45
+ Args:
46
+ trace_id: Unique identifier for this trace
47
+ root_api: The root API call (e.g., "POST /api/orders")
48
+ """
49
+ self.trace_id = trace_id
50
+ self.buffer = TraceBuffer(trace_id, root_api)
51
+ self.depth = 0
52
+ self._call_stack: List[str] = []
53
+
54
+ @classmethod
55
+ def start_trace(cls, root_api: str) -> 'TraceContext':
56
+ """
57
+ Start a new trace.
58
+
59
+ Generates a unique trace ID and creates a new context.
60
+ Sets the context as the active trace.
61
+
62
+ Args:
63
+ root_api: The root API call (e.g., "POST /api/orders")
64
+
65
+ Returns:
66
+ New TraceContext instance
67
+ """
68
+ # Generate short UUID for readability (first 13 chars)
69
+ trace_id = str(uuid.uuid4())[:13]
70
+ ctx = cls(trace_id, root_api)
71
+ _trace_context.set(ctx)
72
+ return ctx
73
+
74
+ @classmethod
75
+ def get_current(cls) -> Optional['TraceContext']:
76
+ """
77
+ Get the current active trace context.
78
+
79
+ Returns:
80
+ Active TraceContext or None if no trace is active
81
+ """
82
+ return _trace_context.get()
83
+
84
+ @classmethod
85
+ def end_trace(cls) -> Optional[TraceBuffer]:
86
+ """
87
+ End the current trace and return the buffer.
88
+
89
+ Clears the active context.
90
+
91
+ Returns:
92
+ TraceBuffer containing all trace entries, or None if no active trace
93
+ """
94
+ ctx = _trace_context.get()
95
+ if ctx:
96
+ _trace_context.set(None)
97
+ return ctx.buffer
98
+ return None
99
+
100
+ def push_call(self, func_name: str) -> int:
101
+ """
102
+ Push a function call onto the stack.
103
+
104
+ Increments depth and tracks the function name.
105
+
106
+ Args:
107
+ func_name: Name of the function being called
108
+
109
+ Returns:
110
+ Depth level before increment (for logging)
111
+ """
112
+ self._call_stack.append(func_name)
113
+ depth = self.depth
114
+ self.depth += 1
115
+ return depth
116
+
117
+ def pop_call(self) -> None:
118
+ """
119
+ Pop a function call from the stack.
120
+
121
+ Decrements depth and removes the function from tracking.
122
+ """
123
+ if self._call_stack:
124
+ self._call_stack.pop()
125
+ self.depth -= 1