x-ipe 1.0.24__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.
- x_ipe/app.py +25 -3
- x_ipe/handlers/terminal_handlers.py +6 -0
- x_ipe/handlers/voice_handlers.py +5 -0
- x_ipe/resources/copilot-instructions.md +19 -6
- x_ipe/resources/skills/lesson-learned/SKILL.md +208 -0
- x_ipe/resources/skills/lesson-learned/references/examples.md +238 -0
- x_ipe/resources/skills/project-quality-board-management/SKILL.md +135 -298
- x_ipe/resources/skills/project-quality-board-management/references/evaluation-principles.md +213 -0
- x_ipe/resources/skills/project-quality-board-management/references/evaluation-procedures.md +214 -0
- x_ipe/resources/skills/project-quality-board-management/templates/quality-report.md +70 -18
- x_ipe/resources/skills/task-execution-guideline/SKILL.md +2 -2
- x_ipe/resources/skills/task-execution-guideline/templates/task-record.yaml +1 -1
- x_ipe/resources/skills/task-type-code-implementation/SKILL.md +72 -270
- x_ipe/resources/skills/task-type-code-implementation/references/implementation-guidelines.md +432 -0
- x_ipe/resources/skills/task-type-code-refactor-v2/SKILL.md +127 -353
- x_ipe/resources/skills/task-type-code-refactor-v2/references/refactoring-techniques.md +373 -0
- x_ipe/resources/skills/task-type-feature-breakdown/SKILL.md +31 -243
- x_ipe/resources/skills/task-type-feature-breakdown/references/breakdown-guidelines.md +330 -0
- x_ipe/resources/skills/task-type-feature-refinement/SKILL.md +27 -180
- x_ipe/resources/skills/task-type-feature-refinement/references/specification-writing-guide.md +267 -0
- x_ipe/resources/skills/task-type-idea-mockup/SKILL.md +38 -276
- x_ipe/resources/skills/task-type-idea-mockup/references/mockup-guidelines.md +299 -0
- x_ipe/resources/skills/task-type-idea-to-architecture/SKILL.md +20 -218
- x_ipe/resources/skills/task-type-idea-to-architecture/references/architecture-patterns.md +342 -0
- x_ipe/resources/skills/task-type-ideation/SKILL.md +10 -266
- x_ipe/resources/skills/task-type-ideation/references/folder-naming-guide.md +55 -0
- x_ipe/resources/skills/task-type-ideation/references/tool-usage-guide.md +236 -0
- x_ipe/resources/skills/task-type-ideation-v2/SKILL.md +488 -0
- x_ipe/resources/skills/task-type-ideation-v2/references/examples.md +377 -0
- x_ipe/resources/skills/task-type-ideation-v2/references/folder-naming-guide.md +74 -0
- x_ipe/resources/skills/task-type-ideation-v2/references/tool-usage-guide.md +145 -0
- x_ipe/resources/skills/task-type-ideation-v2/references/visualization-guide.md +160 -0
- x_ipe/resources/skills/task-type-ideation-v2/templates/idea-summary.md +86 -0
- x_ipe/resources/skills/task-type-refactoring-analysis/SKILL.md +83 -145
- x_ipe/resources/skills/task-type-refactoring-analysis/references/output-schema.md +172 -0
- x_ipe/resources/skills/task-type-technical-design/SKILL.md +28 -214
- x_ipe/resources/skills/task-type-technical-design/references/design-templates.md +422 -0
- x_ipe/resources/skills/task-type-test-generation/SKILL.md +47 -332
- x_ipe/resources/skills/task-type-test-generation/references/test-patterns.md +368 -0
- x_ipe/resources/skills/tool-tracing-creator/SKILL.md +312 -0
- x_ipe/resources/skills/tool-tracing-creator/references/examples.md +324 -0
- x_ipe/resources/skills/tool-tracing-instrumentation/SKILL.md +373 -0
- x_ipe/resources/skills/tool-tracing-instrumentation/references/examples.md +264 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/SKILL.md +486 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/10. example-gate-conditions.md +73 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/11. reference-quality-standards.md +127 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/2. reference-section-order.md +127 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/3. example-step-based-code-review.md +84 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/4. example-step-based-feature-implementation.md +113 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/5. example-function-based-validation.md +73 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/6. example-function-based-analysis.md +94 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/7. example-task-io-code-implementation.md +36 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/8. example-structured-summary.md +43 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/9. example-dor-dod.md +77 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/examples.md +429 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/skill-general-guidelines-v2.md +611 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-meta.md +153 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-task-based.md +324 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-task-category.md +109 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-tool.md +205 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-meta.md +334 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-task-based.md +279 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-tool.md +175 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-workflow-orchestration.md +329 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/SKILL.md +487 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/references/examples.md +377 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/references/folder-naming-guide.md +74 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/references/tool-usage-guide.md +145 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/references/visualization-guide.md +160 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/templates/idea-summary.md +86 -0
- x_ipe/routes/__init__.py +2 -0
- x_ipe/routes/ideas_routes.py +17 -0
- x_ipe/routes/kb_routes.py +80 -0
- x_ipe/routes/main_routes.py +18 -0
- x_ipe/routes/project_routes.py +7 -0
- x_ipe/routes/proxy_routes.py +2 -0
- x_ipe/routes/quality_evaluation_routes.py +193 -0
- x_ipe/routes/settings_routes.py +6 -0
- x_ipe/routes/tools_routes.py +6 -0
- x_ipe/routes/tracing_routes.py +232 -0
- x_ipe/routes/uiux_feedback_routes.py +30 -0
- x_ipe/services/__init__.py +5 -0
- x_ipe/services/config_service.py +6 -0
- x_ipe/services/file_service.py +20 -0
- x_ipe/services/homepage_service.py +160 -0
- x_ipe/services/ideas_service.py +19 -0
- x_ipe/services/kb_service.py +378 -0
- x_ipe/services/proxy_service.py +4 -0
- x_ipe/services/settings_service.py +13 -0
- x_ipe/services/skills_service.py +4 -0
- x_ipe/services/terminal_service.py +24 -0
- x_ipe/services/themes_service.py +4 -0
- x_ipe/services/tools_config_service.py +4 -0
- x_ipe/services/tracing_service.py +333 -0
- x_ipe/services/uiux_feedback_service.py +32 -0
- x_ipe/services/voice_input_service_v2.py +11 -0
- x_ipe/static/css/base.css +7 -0
- x_ipe/static/css/homepage-infinity.css +330 -0
- x_ipe/static/css/kb-core.css +301 -0
- x_ipe/static/css/quality-evaluation.css +345 -0
- x_ipe/static/css/sidebar.css +14 -4
- x_ipe/static/css/terminal.css +1 -0
- x_ipe/static/css/tracing-dashboard.css +796 -0
- x_ipe/static/css/workplace.css +20 -0
- x_ipe/static/img/homepage-infinity-loop.png +0 -0
- x_ipe/static/js/features/homepage-infinity.js +314 -0
- x_ipe/static/js/features/kb-core.js +371 -0
- x_ipe/static/js/features/quality-evaluation.js +387 -0
- x_ipe/static/js/features/sidebar.js +255 -12
- x_ipe/static/js/features/tracing-dashboard.js +855 -0
- x_ipe/static/js/features/tracing-graph.js +1031 -0
- x_ipe/static/js/features/tree-search.js +6 -2
- x_ipe/static/js/features/workplace.js +200 -6
- x_ipe/static/js/init.js +76 -0
- x_ipe/static/js/uiux-feedback.js +18 -2
- x_ipe/templates/base.html +19 -0
- x_ipe/templates/index.html +7 -1
- x_ipe/templates/knowledge-base.html +110 -0
- x_ipe/templates/workplace.html +4 -0
- x_ipe/tracing/__init__.py +37 -0
- x_ipe/tracing/buffer.py +135 -0
- x_ipe/tracing/context.py +125 -0
- x_ipe/tracing/decorator.py +288 -0
- x_ipe/tracing/middleware.py +197 -0
- x_ipe/tracing/parser.py +235 -0
- x_ipe/tracing/redactor.py +111 -0
- x_ipe/tracing/writer.py +122 -0
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/METADATA +2 -2
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/RECORD +132 -62
- x_ipe/resources/skills/x-ipe-skill-creator/SKILL.md +0 -329
- x_ipe/resources/skills/x-ipe-skill-creator/references/output-patterns.md +0 -169
- x_ipe/resources/skills/x-ipe-skill-creator/references/skill-structure.md +0 -162
- x_ipe/resources/skills/x-ipe-skill-creator/references/workflows.md +0 -110
- x_ipe/resources/skills/x-ipe-skill-creator/templates/references/examples.md +0 -113
- x_ipe/resources/skills/x-ipe-skill-creator/templates/skill-category-skill.md +0 -296
- x_ipe/resources/skills/x-ipe-skill-creator/templates/task-type-skill.md +0 -269
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/WHEEL +0 -0
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/entry_points.txt +0 -0
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FEATURE-024: Project Quality Evaluation UI
|
|
3
|
+
|
|
4
|
+
API routes for quality evaluation file management.
|
|
5
|
+
|
|
6
|
+
Provides REST endpoints for:
|
|
7
|
+
- GET /api/quality-evaluation/status - Get folder status and versions
|
|
8
|
+
- GET /api/quality-evaluation/content - Get markdown content for a version
|
|
9
|
+
"""
|
|
10
|
+
from flask import Blueprint, request, jsonify, current_app
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
import re
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
|
|
15
|
+
from x_ipe.tracing import x_ipe_tracing
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
quality_evaluation_bp = Blueprint('quality_evaluation', __name__, url_prefix='/api/quality-evaluation')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
QUALITY_EVAL_FOLDER = 'x-ipe-docs/quality-evaluation'
|
|
22
|
+
EVAL_FILE_PREFIX = 'project-quality-evaluation'
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_project_root() -> Path:
|
|
26
|
+
"""Get project root from app config."""
|
|
27
|
+
return Path(current_app.config.get('PROJECT_ROOT', '.'))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@x_ipe_tracing(level="INFO")
|
|
31
|
+
def get_evaluation_folder() -> Path:
|
|
32
|
+
"""Get the quality evaluation folder path."""
|
|
33
|
+
return get_project_root() / QUALITY_EVAL_FOLDER
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@x_ipe_tracing(level="INFO")
|
|
37
|
+
def parse_version_from_filename(filename: str) -> str:
|
|
38
|
+
"""Extract version number from filename.
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
project-quality-evaluation.md -> v5 (current)
|
|
42
|
+
project-quality-evaluation-v4.md -> v4
|
|
43
|
+
"""
|
|
44
|
+
if filename == f'{EVAL_FILE_PREFIX}.md':
|
|
45
|
+
return 'current'
|
|
46
|
+
match = re.match(rf'{EVAL_FILE_PREFIX}-v(\d+)\.md', filename)
|
|
47
|
+
if match:
|
|
48
|
+
return f'v{match.group(1)}'
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@x_ipe_tracing(level="INFO")
|
|
53
|
+
def get_file_date(file_path: Path) -> str:
|
|
54
|
+
"""Get formatted modification date for a file."""
|
|
55
|
+
try:
|
|
56
|
+
mtime = file_path.stat().st_mtime
|
|
57
|
+
dt = datetime.fromtimestamp(mtime)
|
|
58
|
+
return dt.strftime('%b %d')
|
|
59
|
+
except Exception:
|
|
60
|
+
return ''
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@x_ipe_tracing(level="INFO")
|
|
64
|
+
def scan_versions(folder: Path) -> list:
|
|
65
|
+
"""Scan folder for evaluation versions.
|
|
66
|
+
|
|
67
|
+
Returns list of version dicts sorted by version number (newest first).
|
|
68
|
+
Latest (current) file is always first.
|
|
69
|
+
"""
|
|
70
|
+
if not folder.exists():
|
|
71
|
+
return []
|
|
72
|
+
|
|
73
|
+
versions = []
|
|
74
|
+
current_file = folder / f'{EVAL_FILE_PREFIX}.md'
|
|
75
|
+
|
|
76
|
+
# Check for current (latest) file first
|
|
77
|
+
if current_file.exists():
|
|
78
|
+
# Count existing versioned files to determine current version number
|
|
79
|
+
versioned_files = list(folder.glob(f'{EVAL_FILE_PREFIX}-v*.md'))
|
|
80
|
+
max_version = 0
|
|
81
|
+
for vf in versioned_files:
|
|
82
|
+
match = re.match(rf'{EVAL_FILE_PREFIX}-v(\d+)\.md', vf.name)
|
|
83
|
+
if match:
|
|
84
|
+
max_version = max(max_version, int(match.group(1)))
|
|
85
|
+
|
|
86
|
+
current_version = max_version + 1
|
|
87
|
+
versions.append({
|
|
88
|
+
'version': f'v{current_version}',
|
|
89
|
+
'filename': current_file.name,
|
|
90
|
+
'date': get_file_date(current_file),
|
|
91
|
+
'is_current': True
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
# Scan for versioned files
|
|
95
|
+
versioned_files = sorted(
|
|
96
|
+
folder.glob(f'{EVAL_FILE_PREFIX}-v*.md'),
|
|
97
|
+
key=lambda f: int(re.search(r'-v(\d+)\.md', f.name).group(1)),
|
|
98
|
+
reverse=True
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
for vf in versioned_files:
|
|
102
|
+
match = re.match(rf'{EVAL_FILE_PREFIX}-v(\d+)\.md', vf.name)
|
|
103
|
+
if match:
|
|
104
|
+
versions.append({
|
|
105
|
+
'version': f'v{match.group(1)}',
|
|
106
|
+
'filename': vf.name,
|
|
107
|
+
'date': get_file_date(vf),
|
|
108
|
+
'is_current': False
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
# Limit to 5 most recent versions
|
|
112
|
+
return versions[:5]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@quality_evaluation_bp.route('/status', methods=['GET'])
|
|
116
|
+
@x_ipe_tracing(level="INFO")
|
|
117
|
+
def get_status():
|
|
118
|
+
"""
|
|
119
|
+
GET /api/quality-evaluation/status
|
|
120
|
+
|
|
121
|
+
Get folder status and available versions.
|
|
122
|
+
|
|
123
|
+
Response:
|
|
124
|
+
{
|
|
125
|
+
"exists": true,
|
|
126
|
+
"folder_path": "x-ipe-docs/quality-evaluation",
|
|
127
|
+
"versions": [
|
|
128
|
+
{"version": "v5", "filename": "project-quality-evaluation.md", "date": "Feb 1", "is_current": true},
|
|
129
|
+
{"version": "v4", "filename": "project-quality-evaluation-v4.md", "date": "Jan 31", "is_current": false}
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
"""
|
|
133
|
+
folder = get_evaluation_folder()
|
|
134
|
+
versions = scan_versions(folder)
|
|
135
|
+
|
|
136
|
+
return jsonify({
|
|
137
|
+
'exists': len(versions) > 0,
|
|
138
|
+
'folder_path': QUALITY_EVAL_FOLDER,
|
|
139
|
+
'versions': versions
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@quality_evaluation_bp.route('/content', methods=['GET'])
|
|
144
|
+
@x_ipe_tracing(level="INFO")
|
|
145
|
+
def get_content():
|
|
146
|
+
"""
|
|
147
|
+
GET /api/quality-evaluation/content
|
|
148
|
+
|
|
149
|
+
Get markdown content for a specific version.
|
|
150
|
+
|
|
151
|
+
Query Parameters:
|
|
152
|
+
version (optional): Version to retrieve (e.g., "v4"). Default: latest.
|
|
153
|
+
|
|
154
|
+
Response:
|
|
155
|
+
{
|
|
156
|
+
"content": "# Project Quality Evaluation...",
|
|
157
|
+
"version": "v5",
|
|
158
|
+
"filename": "project-quality-evaluation.md",
|
|
159
|
+
"path": "x-ipe-docs/quality-evaluation/project-quality-evaluation.md"
|
|
160
|
+
}
|
|
161
|
+
"""
|
|
162
|
+
folder = get_evaluation_folder()
|
|
163
|
+
requested_version = request.args.get('version')
|
|
164
|
+
|
|
165
|
+
versions = scan_versions(folder)
|
|
166
|
+
if not versions:
|
|
167
|
+
return jsonify({'error': 'No evaluation file found'}), 404
|
|
168
|
+
|
|
169
|
+
# Find the requested version or use latest
|
|
170
|
+
target_version = None
|
|
171
|
+
if requested_version:
|
|
172
|
+
for v in versions:
|
|
173
|
+
if v['version'] == requested_version:
|
|
174
|
+
target_version = v
|
|
175
|
+
break
|
|
176
|
+
if not target_version:
|
|
177
|
+
return jsonify({'error': f'Version {requested_version} not found'}), 404
|
|
178
|
+
else:
|
|
179
|
+
target_version = versions[0] # Latest
|
|
180
|
+
|
|
181
|
+
# Read the file content
|
|
182
|
+
file_path = folder / target_version['filename']
|
|
183
|
+
try:
|
|
184
|
+
content = file_path.read_text(encoding='utf-8')
|
|
185
|
+
except Exception as e:
|
|
186
|
+
return jsonify({'error': f'Failed to read file: {str(e)}'}), 500
|
|
187
|
+
|
|
188
|
+
return jsonify({
|
|
189
|
+
'content': content,
|
|
190
|
+
'version': target_version['version'],
|
|
191
|
+
'filename': target_version['filename'],
|
|
192
|
+
'path': f"{QUALITY_EVAL_FOLDER}/{target_version['filename']}"
|
|
193
|
+
})
|
x_ipe/routes/settings_routes.py
CHANGED
|
@@ -12,6 +12,8 @@ Provides:
|
|
|
12
12
|
import os
|
|
13
13
|
from flask import Blueprint, render_template, jsonify, request, current_app
|
|
14
14
|
|
|
15
|
+
from x_ipe.tracing import x_ipe_tracing
|
|
16
|
+
|
|
15
17
|
settings_bp = Blueprint('settings', __name__)
|
|
16
18
|
|
|
17
19
|
|
|
@@ -21,6 +23,7 @@ def get_settings_service():
|
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
@settings_bp.route('/settings')
|
|
26
|
+
@x_ipe_tracing()
|
|
24
27
|
def settings_page():
|
|
25
28
|
"""
|
|
26
29
|
GET /settings
|
|
@@ -33,6 +36,7 @@ def settings_page():
|
|
|
33
36
|
|
|
34
37
|
|
|
35
38
|
@settings_bp.route('/api/settings', methods=['GET'])
|
|
39
|
+
@x_ipe_tracing()
|
|
36
40
|
def get_settings():
|
|
37
41
|
"""
|
|
38
42
|
GET /api/settings
|
|
@@ -50,6 +54,7 @@ def get_settings():
|
|
|
50
54
|
|
|
51
55
|
|
|
52
56
|
@settings_bp.route('/api/settings', methods=['POST'])
|
|
57
|
+
@x_ipe_tracing()
|
|
53
58
|
def save_settings():
|
|
54
59
|
"""
|
|
55
60
|
POST /api/settings
|
|
@@ -96,6 +101,7 @@ def save_settings():
|
|
|
96
101
|
|
|
97
102
|
|
|
98
103
|
@settings_bp.route('/api/config', methods=['GET'])
|
|
104
|
+
@x_ipe_tracing()
|
|
99
105
|
def get_config():
|
|
100
106
|
"""
|
|
101
107
|
GET /api/config
|
x_ipe/routes/tools_routes.py
CHANGED
|
@@ -14,6 +14,7 @@ import json
|
|
|
14
14
|
from flask import Blueprint, jsonify, request, current_app
|
|
15
15
|
|
|
16
16
|
from x_ipe.services import ToolsConfigService, ThemesService
|
|
17
|
+
from x_ipe.tracing import x_ipe_tracing
|
|
17
18
|
|
|
18
19
|
tools_bp = Blueprint('tools', __name__)
|
|
19
20
|
|
|
@@ -31,6 +32,7 @@ def _get_themes_service():
|
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
@tools_bp.route('/api/config/tools', methods=['GET'])
|
|
35
|
+
@x_ipe_tracing()
|
|
34
36
|
def get_tools_config():
|
|
35
37
|
"""
|
|
36
38
|
GET /api/config/tools
|
|
@@ -56,6 +58,7 @@ def get_tools_config():
|
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
@tools_bp.route('/api/config/tools', methods=['POST'])
|
|
61
|
+
@x_ipe_tracing()
|
|
59
62
|
def save_tools_config():
|
|
60
63
|
"""
|
|
61
64
|
POST /api/config/tools
|
|
@@ -93,6 +96,7 @@ def save_tools_config():
|
|
|
93
96
|
|
|
94
97
|
|
|
95
98
|
@tools_bp.route('/api/config/copilot-prompt', methods=['GET'])
|
|
99
|
+
@x_ipe_tracing()
|
|
96
100
|
def get_copilot_prompt_config():
|
|
97
101
|
"""
|
|
98
102
|
GET /api/config/copilot-prompt
|
|
@@ -130,6 +134,7 @@ def get_copilot_prompt_config():
|
|
|
130
134
|
# ============================================================
|
|
131
135
|
|
|
132
136
|
@tools_bp.route('/api/themes', methods=['GET'])
|
|
137
|
+
@x_ipe_tracing()
|
|
133
138
|
def list_themes():
|
|
134
139
|
"""
|
|
135
140
|
GET /api/themes
|
|
@@ -163,6 +168,7 @@ def list_themes():
|
|
|
163
168
|
|
|
164
169
|
|
|
165
170
|
@tools_bp.route('/api/themes/<name>', methods=['GET'])
|
|
171
|
+
@x_ipe_tracing()
|
|
166
172
|
def get_theme_detail(name):
|
|
167
173
|
"""
|
|
168
174
|
GET /api/themes/<name>
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FEATURE-023: Application Action Tracing - Core
|
|
3
|
+
|
|
4
|
+
Tracing API routes for controlling tracing and viewing logs.
|
|
5
|
+
|
|
6
|
+
Provides REST endpoints for:
|
|
7
|
+
- GET /api/tracing/status - Get tracing configuration
|
|
8
|
+
- POST /api/tracing/start - Start tracing for duration
|
|
9
|
+
- POST /api/tracing/stop - Stop tracing immediately
|
|
10
|
+
- GET /api/tracing/logs - List trace log files
|
|
11
|
+
- DELETE /api/tracing/logs - Delete all trace logs
|
|
12
|
+
"""
|
|
13
|
+
from flask import Blueprint, request, jsonify, current_app
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from x_ipe.services.tracing_service import TracingService
|
|
17
|
+
from x_ipe.tracing import x_ipe_tracing
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
tracing_bp = Blueprint('tracing', __name__, url_prefix='/api/tracing')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_service() -> TracingService:
|
|
24
|
+
"""Get TracingService instance for current app."""
|
|
25
|
+
project_root = current_app.config.get('PROJECT_ROOT', '.')
|
|
26
|
+
return TracingService(project_root)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@tracing_bp.route('/status', methods=['GET'])
|
|
30
|
+
@x_ipe_tracing()
|
|
31
|
+
def get_status():
|
|
32
|
+
"""
|
|
33
|
+
GET /api/tracing/status
|
|
34
|
+
|
|
35
|
+
Get current tracing configuration and status.
|
|
36
|
+
|
|
37
|
+
Response:
|
|
38
|
+
{
|
|
39
|
+
"enabled": false,
|
|
40
|
+
"stop_at": "2026-02-01T03:30:00Z",
|
|
41
|
+
"log_path": "instance/traces/",
|
|
42
|
+
"retention_hours": 24,
|
|
43
|
+
"ignored_apis": [],
|
|
44
|
+
"active": true
|
|
45
|
+
}
|
|
46
|
+
"""
|
|
47
|
+
service = get_service()
|
|
48
|
+
config = service.get_config()
|
|
49
|
+
config["active"] = service.is_active()
|
|
50
|
+
return jsonify(config)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@tracing_bp.route('/start', methods=['POST'])
|
|
54
|
+
@x_ipe_tracing()
|
|
55
|
+
def start_tracing():
|
|
56
|
+
"""
|
|
57
|
+
POST /api/tracing/start
|
|
58
|
+
|
|
59
|
+
Start tracing for specified duration.
|
|
60
|
+
|
|
61
|
+
Request:
|
|
62
|
+
{
|
|
63
|
+
"duration_minutes": 3 | 15 | 30
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
Response:
|
|
67
|
+
{
|
|
68
|
+
"success": true,
|
|
69
|
+
"stop_at": "2026-02-01T03:33:00Z"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Errors:
|
|
73
|
+
400 - Invalid duration (must be 3, 15, or 30)
|
|
74
|
+
"""
|
|
75
|
+
data = request.get_json() or {}
|
|
76
|
+
duration = data.get('duration_minutes', 3)
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
service = get_service()
|
|
80
|
+
result = service.start(duration)
|
|
81
|
+
return jsonify(result)
|
|
82
|
+
except ValueError as e:
|
|
83
|
+
return jsonify({"error": str(e)}), 400
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@tracing_bp.route('/stop', methods=['POST'])
|
|
87
|
+
@x_ipe_tracing()
|
|
88
|
+
def stop_tracing():
|
|
89
|
+
"""
|
|
90
|
+
POST /api/tracing/stop
|
|
91
|
+
|
|
92
|
+
Stop tracing immediately.
|
|
93
|
+
|
|
94
|
+
Response:
|
|
95
|
+
{
|
|
96
|
+
"success": true
|
|
97
|
+
}
|
|
98
|
+
"""
|
|
99
|
+
service = get_service()
|
|
100
|
+
result = service.stop()
|
|
101
|
+
return jsonify(result)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@tracing_bp.route('/logs', methods=['GET'])
|
|
105
|
+
@x_ipe_tracing()
|
|
106
|
+
def list_logs():
|
|
107
|
+
"""
|
|
108
|
+
GET /api/tracing/logs
|
|
109
|
+
|
|
110
|
+
List all trace log files.
|
|
111
|
+
|
|
112
|
+
Response:
|
|
113
|
+
[
|
|
114
|
+
{
|
|
115
|
+
"trace_id": "abc-123",
|
|
116
|
+
"filename": "20260201-033000-post-api-orders-abc-123.log",
|
|
117
|
+
"size": 1234,
|
|
118
|
+
"timestamp": "2026-02-01T03:30:00"
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
"""
|
|
122
|
+
service = get_service()
|
|
123
|
+
logs = service.list_logs()
|
|
124
|
+
return jsonify(logs)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@tracing_bp.route('/logs', methods=['DELETE'])
|
|
128
|
+
@x_ipe_tracing()
|
|
129
|
+
def delete_logs():
|
|
130
|
+
"""
|
|
131
|
+
DELETE /api/tracing/logs
|
|
132
|
+
|
|
133
|
+
Delete all trace log files.
|
|
134
|
+
|
|
135
|
+
Response:
|
|
136
|
+
{
|
|
137
|
+
"deleted": 5
|
|
138
|
+
}
|
|
139
|
+
"""
|
|
140
|
+
service = get_service()
|
|
141
|
+
deleted = service.delete_all_logs()
|
|
142
|
+
return jsonify({"deleted": deleted})
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@tracing_bp.route('/logs/<trace_id>', methods=['GET'])
|
|
146
|
+
@x_ipe_tracing()
|
|
147
|
+
def get_trace(trace_id):
|
|
148
|
+
"""
|
|
149
|
+
GET /api/tracing/logs/<trace_id>
|
|
150
|
+
|
|
151
|
+
Get parsed trace data for DAG visualization.
|
|
152
|
+
|
|
153
|
+
Response:
|
|
154
|
+
{
|
|
155
|
+
"trace_id": "abc-123",
|
|
156
|
+
"api": "POST /api/orders",
|
|
157
|
+
"timestamp": "2026-02-01T03:30:00",
|
|
158
|
+
"total_time_ms": 245,
|
|
159
|
+
"status": "success",
|
|
160
|
+
"nodes": [
|
|
161
|
+
{
|
|
162
|
+
"id": "node-0",
|
|
163
|
+
"label": "POST /api/orders",
|
|
164
|
+
"timing": "245ms",
|
|
165
|
+
"status": "success",
|
|
166
|
+
"level": "API",
|
|
167
|
+
"input": "{}",
|
|
168
|
+
"output": "{}",
|
|
169
|
+
"error": null
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"edges": [
|
|
173
|
+
{"source": "node-0", "target": "node-1"}
|
|
174
|
+
],
|
|
175
|
+
"filename": "20260201-post-api-orders-abc123.log"
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
Errors:
|
|
179
|
+
404 - Trace not found
|
|
180
|
+
"""
|
|
181
|
+
service = get_service()
|
|
182
|
+
result = service.get_trace(trace_id)
|
|
183
|
+
|
|
184
|
+
if result is None:
|
|
185
|
+
return jsonify({"error": f"Trace not found: {trace_id}"}), 404
|
|
186
|
+
|
|
187
|
+
return jsonify(result)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@tracing_bp.route('/ignored', methods=['GET'])
|
|
191
|
+
@x_ipe_tracing()
|
|
192
|
+
def get_ignored_apis():
|
|
193
|
+
"""
|
|
194
|
+
GET /api/tracing/ignored
|
|
195
|
+
|
|
196
|
+
Get list of ignored API patterns.
|
|
197
|
+
|
|
198
|
+
Response:
|
|
199
|
+
{
|
|
200
|
+
"patterns": ["/api/health/*", "/api/status"]
|
|
201
|
+
}
|
|
202
|
+
"""
|
|
203
|
+
service = get_service()
|
|
204
|
+
config = service.get_config()
|
|
205
|
+
return jsonify({"patterns": config.get("ignored_apis", [])})
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@tracing_bp.route('/ignored', methods=['POST'])
|
|
209
|
+
@x_ipe_tracing()
|
|
210
|
+
def update_ignored_apis():
|
|
211
|
+
"""
|
|
212
|
+
POST /api/tracing/ignored
|
|
213
|
+
|
|
214
|
+
Update list of ignored API patterns.
|
|
215
|
+
|
|
216
|
+
Request:
|
|
217
|
+
{
|
|
218
|
+
"patterns": ["/api/health/*", "/api/status"]
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
Response:
|
|
222
|
+
{
|
|
223
|
+
"success": true
|
|
224
|
+
}
|
|
225
|
+
"""
|
|
226
|
+
data = request.get_json() or {}
|
|
227
|
+
patterns = data.get('patterns', [])
|
|
228
|
+
|
|
229
|
+
service = get_service()
|
|
230
|
+
service.update_ignored_apis(patterns)
|
|
231
|
+
|
|
232
|
+
return jsonify({"success": True})
|
|
@@ -5,12 +5,14 @@ API routes for submitting UI/UX feedback.
|
|
|
5
5
|
"""
|
|
6
6
|
from flask import Blueprint, request, jsonify, current_app
|
|
7
7
|
from ..services.uiux_feedback_service import UiuxFeedbackService
|
|
8
|
+
from x_ipe.tracing import x_ipe_tracing
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
uiux_feedback_bp = Blueprint('uiux_feedback', __name__)
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
@uiux_feedback_bp.route('/api/uiux-feedback', methods=['GET'])
|
|
15
|
+
@x_ipe_tracing()
|
|
14
16
|
def list_feedback():
|
|
15
17
|
"""
|
|
16
18
|
List recent feedback entries.
|
|
@@ -30,7 +32,35 @@ def list_feedback():
|
|
|
30
32
|
return jsonify({'entries': entries}), 200
|
|
31
33
|
|
|
32
34
|
|
|
35
|
+
@uiux_feedback_bp.route('/api/uiux-feedback/<feedback_id>', methods=['DELETE'])
|
|
36
|
+
@x_ipe_tracing()
|
|
37
|
+
def delete_feedback(feedback_id):
|
|
38
|
+
"""
|
|
39
|
+
Delete a feedback entry by ID.
|
|
40
|
+
|
|
41
|
+
Path params:
|
|
42
|
+
feedback_id: The feedback folder name/ID
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
200: {"success": true}
|
|
46
|
+
404: {"success": false, "error": "Feedback not found"}
|
|
47
|
+
500: {"success": false, "error": "..."}
|
|
48
|
+
"""
|
|
49
|
+
project_root = current_app.config.get('PROJECT_ROOT', '.')
|
|
50
|
+
|
|
51
|
+
service = UiuxFeedbackService(project_root)
|
|
52
|
+
result = service.delete_feedback(feedback_id)
|
|
53
|
+
|
|
54
|
+
if result['success']:
|
|
55
|
+
return jsonify(result), 200
|
|
56
|
+
elif 'not found' in result.get('error', '').lower():
|
|
57
|
+
return jsonify(result), 404
|
|
58
|
+
else:
|
|
59
|
+
return jsonify(result), 500
|
|
60
|
+
|
|
61
|
+
|
|
33
62
|
@uiux_feedback_bp.route('/api/uiux-feedback', methods=['POST'])
|
|
63
|
+
@x_ipe_tracing()
|
|
34
64
|
def submit_feedback():
|
|
35
65
|
"""
|
|
36
66
|
Submit UI/UX feedback entry.
|
x_ipe/services/__init__.py
CHANGED
|
@@ -26,6 +26,9 @@ from .file_service import (
|
|
|
26
26
|
# Ideas Service (FEATURE-008)
|
|
27
27
|
from .ideas_service import IdeasService
|
|
28
28
|
|
|
29
|
+
# KB Service (FEATURE-025-A)
|
|
30
|
+
from .kb_service import KBService
|
|
31
|
+
|
|
29
32
|
# Terminal Service (FEATURE-005)
|
|
30
33
|
from .terminal_service import (
|
|
31
34
|
OutputBuffer,
|
|
@@ -80,6 +83,8 @@ __all__ = [
|
|
|
80
83
|
'ContentService',
|
|
81
84
|
# Ideas
|
|
82
85
|
'IdeasService',
|
|
86
|
+
# KB
|
|
87
|
+
'KBService',
|
|
83
88
|
# Terminal
|
|
84
89
|
'OutputBuffer',
|
|
85
90
|
'PersistentSession',
|
x_ipe/services/config_service.py
CHANGED
|
@@ -10,6 +10,8 @@ from pathlib import Path
|
|
|
10
10
|
from typing import Optional
|
|
11
11
|
from dataclasses import dataclass
|
|
12
12
|
|
|
13
|
+
from x_ipe.tracing import x_ipe_tracing
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
CONFIG_FILE_NAME = '.x-ipe.yaml'
|
|
15
17
|
MAX_PARENT_LEVELS = 20
|
|
@@ -31,14 +33,17 @@ class ConfigData:
|
|
|
31
33
|
file_tree_scope: str
|
|
32
34
|
terminal_cwd: str
|
|
33
35
|
|
|
36
|
+
@x_ipe_tracing()
|
|
34
37
|
def get_file_tree_path(self) -> str:
|
|
35
38
|
"""Return the path for file tree based on file_tree_scope."""
|
|
36
39
|
return self.project_root if self.file_tree_scope == "project_root" else self.x_ipe_app
|
|
37
40
|
|
|
41
|
+
@x_ipe_tracing()
|
|
38
42
|
def get_terminal_cwd(self) -> str:
|
|
39
43
|
"""Return the path for terminal cwd based on terminal_cwd setting."""
|
|
40
44
|
return self.project_root if self.terminal_cwd == "project_root" else self.x_ipe_app
|
|
41
45
|
|
|
46
|
+
@x_ipe_tracing()
|
|
42
47
|
def to_dict(self) -> dict:
|
|
43
48
|
"""Convert to dictionary for API response."""
|
|
44
49
|
return {
|
|
@@ -74,6 +79,7 @@ class ConfigService:
|
|
|
74
79
|
self._config_data: Optional[ConfigData] = None
|
|
75
80
|
self._error: Optional[str] = None
|
|
76
81
|
|
|
82
|
+
@x_ipe_tracing()
|
|
77
83
|
def load(self) -> Optional[ConfigData]:
|
|
78
84
|
"""
|
|
79
85
|
Discover, parse, and validate config file.
|