mcp-efficiency-engine 0.1.0 → 0.1.1
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.
- package/.github/workflows/autodocs-sync.yml +2 -15
- package/.github/workflows/release-npm.yml +111 -0
- package/FINAL_USAGE_GUIDE.md +56 -0
- package/README.md +133 -0
- package/autodocs/README.md +6 -0
- package/observability/metrics.md +33 -0
- package/observability/scoring-rubric.md +20 -0
- package/orchestrator/wiki/graph_consolidator.py +60 -1
- package/orchestrator/wiki/incremental_engine.py +23 -1
- package/orchestrator/wiki/plugin_manager.py +87 -22
- package/package.json +8 -2
- package/requirements.txt +1 -0
- package/scripts/intake/resolve-routing.py +124 -87
- package/scripts/intake/validate-database-routing.py +13 -4
- package/scripts/intake/validate-rag-routing.py +4 -3
- package/scripts/learning/learning-loop-report.py +28 -10
- package/scripts/ops/llm-token-probe.py +103 -39
- package/scripts/ops/telemetry-benchmark.py +184 -0
- package/scripts/wiki/compiler_main.py +108 -76
- package/scripts/wiki/providers/repo_content_provider.py +51 -0
- package/scripts/wiki/validator.py +40 -15
- package/telemetry/__init__.py +4 -0
- package/telemetry/bootstrap.py +47 -0
- package/telemetry/collector/engine.py +261 -0
- package/telemetry/config.json +20 -0
- package/telemetry/config.py +131 -0
- package/telemetry/context/propagation.py +85 -0
- package/telemetry/events/catalog.py +24 -0
- package/telemetry/events/factory.py +42 -0
- package/telemetry/exporters/base.py +16 -0
- package/telemetry/exporters/console/exporter.py +30 -0
- package/telemetry/exporters/json/exporter.py +34 -0
- package/telemetry/exporters/langsmith/exporter.py +415 -0
- package/telemetry/metrics/aggregator.py +60 -0
- package/telemetry/scoring/efficiency.py +68 -0
- package/telemetry/tracing/span.py +43 -0
- package/observability/evals/chat-token-usage-report.json +0 -64
- package/observability/evals/chat-token-usage-report.md +0 -33
- package/observability/evals/iteration-value-report.json +0 -76
- package/observability/evals/iteration-value-report.md +0 -39
- package/observability/evals/learning-loop-report.json +0 -268
- package/observability/evals/learning-loop-report.md +0 -37
- package/observability/evals/repo-intake-eval-cases.md +0 -23
- package/observability/evals/routing-eval-cases.json +0 -68
- package/observability/evals/routing-eval-cases.md +0 -25
- package/observability/evals/routing-eval-report.json +0 -72
- package/observability/logs/copilot-usage-ingest-report.json +0 -13
- package/observability/logs/iteration-metrics.jsonl +0 -75
- package/observability/logs/learning-feedback.jsonl +0 -152
- package/observability/logs/routing-decisions.jsonl +0 -333
- package/observability/logs/session/agent-pipeline-preflight-20260701-004146.log +0 -8
- package/observability/logs/session/agent-pipeline-preflight-20260701-005554.log +0 -8
- package/observability/logs/session/agent-pipeline-preflight-20260701-010351.log +0 -8
- package/observability/logs/session/agent-pipeline-preflight-20260704-145829.log +0 -8
- package/observability/logs/session/agent-pipeline-preflight-20260704-150021.log +0 -8
- package/observability/logs/session/agent-pipeline-preflight-20260704-154328.log +0 -8
- package/observability/logs/session/bye-20260629-221513.json +0 -39
- package/observability/logs/session/bye-20260629-221545.json +0 -59
- package/observability/logs/session/bye-20260629-222007.json +0 -52
- package/observability/logs/session/bye-20260629-222133.json +0 -59
- package/observability/logs/session/bye-20260629-222412.json +0 -45
- package/observability/logs/session/bye-20260629-223224.json +0 -52
- package/observability/logs/session/bye-20260629-224050.json +0 -59
- package/observability/logs/session/bye-20260630-105732.json +0 -24
- package/observability/logs/session/bye-20260630-211536.json +0 -87
- package/observability/logs/session/bye-20260630-223423.json +0 -87
- package/observability/logs/session/bye-20260630-232534.json +0 -87
- package/observability/logs/session/bye-20260701-003638.json +0 -126
- package/observability/logs/session/bye-20260701-003849.json +0 -126
- package/observability/logs/session/bye-20260701-004315.json +0 -138
- package/observability/logs/session/bye-20260701-004559.json +0 -76
- package/observability/logs/session/bye-20260701-005913.json +0 -138
- package/observability/logs/session/bye-20260701-010753.json +0 -138
- package/observability/logs/session/bye-20260703-194106.json +0 -24
- package/observability/logs/session/bye-20260703-233443.json +0 -76
- package/observability/logs/session/bye-20260703-233653.json +0 -76
- package/observability/logs/session/bye-20260704-150317.json +0 -152
- package/observability/logs/session/bye-20260704-150929.json +0 -75
- package/observability/logs/session/bye-20260704-151050.json +0 -75
- package/observability/logs/session/bye-20260705-115458.json +0 -165
- package/observability/logs/session/codegraph-status-20260701-004228.log +0 -39
- package/observability/logs/session/codegraph-status-20260701-004310.log +0 -39
- package/observability/logs/session/codegraph-status-20260701-005637.log +0 -39
- package/observability/logs/session/codegraph-status-20260701-005908.log +0 -39
- package/observability/logs/session/codegraph-status-20260701-010444.log +0 -39
- package/observability/logs/session/codegraph-status-20260701-010747.log +0 -39
- package/observability/logs/session/codegraph-status-20260704-150137.log +0 -26
- package/observability/logs/session/codegraph-status-20260704-150313.log +0 -28
- package/observability/logs/session/codegraph-status-20260704-154445.log +0 -26
- package/observability/logs/session/codegraph-status-20260705-115454.log +0 -27
- package/observability/logs/session/codegraph-sync-20260701-004211.log +0 -88
- package/observability/logs/session/codegraph-sync-20260701-004241.log +0 -82
- package/observability/logs/session/codegraph-sync-20260701-005620.log +0 -89
- package/observability/logs/session/codegraph-sync-20260701-005840.log +0 -88
- package/observability/logs/session/codegraph-sync-20260701-010419.log +0 -93
- package/observability/logs/session/codegraph-sync-20260701-010609.log +0 -90
- package/observability/logs/session/codegraph-sync-20260704-145856.log +0 -70
- package/observability/logs/session/codegraph-sync-20260704-150047.log +0 -53
- package/observability/logs/session/codegraph-sync-20260704-150204.log +0 -44
- package/observability/logs/session/codegraph-sync-20260704-154353.log +0 -26
- package/observability/logs/session/codegraph-sync-20260705-115337.log +0 -32
- package/observability/logs/session/hi-20260629-221459.json +0 -38
- package/observability/logs/session/hi-20260629-221945.json +0 -59
- package/observability/logs/session/hi-20260629-222108.json +0 -66
- package/observability/logs/session/hi-20260629-222352.json +0 -45
- package/observability/logs/session/hi-20260629-225719.json +0 -59
- package/observability/logs/session/hi-20260629-233722.json +0 -52
- package/observability/logs/session/hi-20260629-233913.json +0 -198
- package/observability/logs/session/hi-20260630-110156.json +0 -177
- package/observability/logs/session/hi-20260630-191243.json +0 -184
- package/observability/logs/session/hi-20260630-230050.json +0 -234
- package/observability/logs/session/hi-20260630-230523.json +0 -227
- package/observability/logs/session/hi-20260630-230855.json +0 -227
- package/observability/logs/session/hi-20260630-231638.json +0 -227
- package/observability/logs/session/hi-20260630-231756.json +0 -219
- package/observability/logs/session/hi-20260701-002842.json +0 -234
- package/observability/logs/session/hi-20260701-003458.json +0 -282
- package/observability/logs/session/hi-20260701-004233.json +0 -290
- package/observability/logs/session/hi-20260701-004554.json +0 -236
- package/observability/logs/session/hi-20260701-005641.json +0 -290
- package/observability/logs/session/hi-20260701-010450.json +0 -290
- package/observability/logs/session/hi-20260703-233854.json +0 -312
- package/observability/logs/session/hi-20260703-234448.json +0 -318
- package/observability/logs/session/hi-20260704-145907.json +0 -353
- package/observability/logs/session/hi-20260704-150141.json +0 -392
- package/observability/logs/session/hi-20260704-154448.json +0 -392
- package/observability/logs/session/iteration-value-refresh-20260701-004309.log +0 -3
- package/observability/logs/session/iteration-value-refresh-20260701-005907.log +0 -3
- package/observability/logs/session/iteration-value-refresh-20260701-010747.log +0 -3
- package/observability/logs/session/iteration-value-refresh-20260704-150312.log +0 -3
- package/observability/logs/session/iteration-value-refresh-20260705-115453.log +0 -3
- package/observability/logs/session/learning-loop-refresh-20260701-004309.log +0 -3
- package/observability/logs/session/learning-loop-refresh-20260701-005906.log +0 -3
- package/observability/logs/session/learning-loop-refresh-20260701-010745.log +0 -3
- package/observability/logs/session/learning-loop-refresh-20260704-150309.log +0 -3
- package/observability/logs/session/learning-loop-refresh-20260705-115450.log +0 -3
- package/observability/logs/session/project-notes-refresh-20260701-004227.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260701-004308.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260701-005636.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260701-005906.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260701-010443.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260701-010744.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260704-150133.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260704-150309.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260704-154442.log +0 -1
- package/observability/logs/session/project-notes-refresh-20260705-115449.log +0 -1
- package/observability/logs/session/repo-intake-20260701-004218.log +0 -6
- package/observability/logs/session/repo-intake-20260701-005626.log +0 -6
- package/observability/logs/session/repo-intake-20260701-010433.log +0 -6
- package/observability/logs/session/repo-intake-20260704-150053.log +0 -6
- package/observability/logs/session/repo-intake-20260704-154404.log +0 -6
- package/observability/logs/session/repo-intake-refresh-20260701-004247.log +0 -6
- package/observability/logs/session/repo-intake-refresh-20260701-005847.log +0 -6
- package/observability/logs/session/repo-intake-refresh-20260701-010615.log +0 -6
- package/observability/logs/session/repo-intake-refresh-20260704-150209.log +0 -6
- package/observability/logs/session/repo-intake-refresh-20260705-115342.log +0 -6
- package/observability/logs/session/repo-registry-validation-20260701-004234.log +0 -2
- package/observability/logs/session/repo-registry-validation-20260701-004556.log +0 -2
- package/observability/logs/session/repo-registry-validation-20260701-005833.log +0 -2
- package/observability/logs/session/repo-registry-validation-20260701-010601.log +0 -2
- package/observability/logs/session/repo-registry-validation-20260704-150155.log +0 -2
- package/observability/logs/session/repo-registry-validation-20260705-115323.log +0 -2
- package/observability/logs/session/repomix-refresh-20260701-003823.log +0 -4236
- package/observability/logs/session/repomix-refresh-20260701-004251.log +0 -4275
- package/observability/logs/session/repomix-refresh-20260701-005850.log +0 -4248
- package/observability/logs/session/repomix-refresh-20260701-010619.log +0 -6531
- package/observability/logs/session/repomix-refresh-20260704-150239.log +0 -652
- package/observability/logs/session/repomix-refresh-20260705-115419.log +0 -178
- package/observability/logs/session/routing-evals-20260701-004221.log +0 -2
- package/observability/logs/session/routing-evals-20260701-004235.log +0 -2
- package/observability/logs/session/routing-evals-20260701-005629.log +0 -2
- package/observability/logs/session/routing-evals-20260701-005834.log +0 -2
- package/observability/logs/session/routing-evals-20260701-010437.log +0 -2
- package/observability/logs/session/routing-evals-20260701-010603.log +0 -2
- package/observability/logs/session/routing-evals-20260704-150125.log +0 -2
- package/observability/logs/session/routing-evals-20260704-150157.log +0 -2
- package/observability/logs/session/routing-evals-20260704-154434.log +0 -2
- package/observability/logs/session/routing-evals-20260705-115327.log +0 -2
- package/observability/logs/session/sibling-discovery-refresh-20260701-004250.log +0 -3
- package/observability/logs/session/sibling-discovery-refresh-20260701-005850.log +0 -3
- package/observability/logs/session/sibling-discovery-refresh-20260701-010618.log +0 -3
- package/observability/logs/session/sibling-discovery-refresh-20260704-150238.log +0 -3
- package/observability/logs/session/sibling-discovery-refresh-20260705-115418.log +0 -3
|
@@ -3,22 +3,8 @@ name: AutoDocs Sync
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
branches: [ main, develop ]
|
|
6
|
-
paths:
|
|
7
|
-
- 'repo-intake/generated/**'
|
|
8
|
-
- 'autodocs/**'
|
|
9
|
-
- 'scripts/wiki/**'
|
|
10
|
-
- 'orchestrator/wiki/**'
|
|
11
|
-
- '.github/skills/wiki-tools.json'
|
|
12
|
-
- '.github/agents/wiki-agent.agent.md'
|
|
13
6
|
pull_request:
|
|
14
7
|
branches: [ main, develop ]
|
|
15
|
-
paths:
|
|
16
|
-
- 'repo-intake/generated/**'
|
|
17
|
-
- 'autodocs/**'
|
|
18
|
-
- 'scripts/wiki/**'
|
|
19
|
-
- 'orchestrator/wiki/**'
|
|
20
|
-
- '.github/skills/wiki-tools.json'
|
|
21
|
-
- '.github/agents/wiki-agent.agent.md'
|
|
22
8
|
workflow_dispatch:
|
|
23
9
|
|
|
24
10
|
permissions:
|
|
@@ -68,7 +54,7 @@ jobs:
|
|
|
68
54
|
echo "- Required artifacts: autodocs/generated + autodocs/site" >> $env:GITHUB_STEP_SUMMARY
|
|
69
55
|
|
|
70
56
|
autodocs-sync:
|
|
71
|
-
if: github.
|
|
57
|
+
if: github.actor != 'github-actions[bot]'
|
|
72
58
|
permissions:
|
|
73
59
|
contents: write
|
|
74
60
|
runs-on: windows-latest
|
|
@@ -89,6 +75,7 @@ jobs:
|
|
|
89
75
|
shell: pwsh
|
|
90
76
|
|
|
91
77
|
- name: Commit projected docs and unified graph
|
|
78
|
+
if: github.event_name != 'pull_request'
|
|
92
79
|
shell: pwsh
|
|
93
80
|
run: |
|
|
94
81
|
git config user.name "github-actions[bot]"
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
name: Release & Publish NPM
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
npm_version:
|
|
9
|
+
description: "Version especifica a publicar (ej. 0.2.0). Si se omite, se autoajusta."
|
|
10
|
+
required: false
|
|
11
|
+
type: string
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
release-and-publish:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout
|
|
22
|
+
uses: actions/checkout@v5
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
|
|
26
|
+
- name: Setup Node.js
|
|
27
|
+
uses: actions/setup-node@v4
|
|
28
|
+
with:
|
|
29
|
+
node-version: 20
|
|
30
|
+
registry-url: https://registry.npmjs.org
|
|
31
|
+
|
|
32
|
+
- name: Resolve publish version
|
|
33
|
+
id: version
|
|
34
|
+
run: |
|
|
35
|
+
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
36
|
+
BASE_VERSION=$(node -p "require('./package.json').version")
|
|
37
|
+
REQUESTED_VERSION="${{ github.event.inputs.npm_version || '' }}"
|
|
38
|
+
|
|
39
|
+
version_exists() {
|
|
40
|
+
npm view "$PACKAGE_NAME@$1" version >/dev/null 2>&1
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if [ -n "$REQUESTED_VERSION" ]; then
|
|
44
|
+
TARGET_VERSION="$REQUESTED_VERSION"
|
|
45
|
+
MODE="explicit"
|
|
46
|
+
else
|
|
47
|
+
TARGET_VERSION="$BASE_VERSION"
|
|
48
|
+
MODE="auto"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if [ "$MODE" = "explicit" ]; then
|
|
52
|
+
if version_exists "$TARGET_VERSION"; then
|
|
53
|
+
echo "Requested version $TARGET_VERSION is already published in npm."
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
else
|
|
57
|
+
CANDIDATE="$TARGET_VERSION"
|
|
58
|
+
while version_exists "$CANDIDATE"; do
|
|
59
|
+
CANDIDATE=$(node -e "const parts = process.argv[1].split('.').map(Number); if (parts.length !== 3 || parts.some(Number.isNaN)) { process.exit(2); } parts[2] += 1; process.stdout.write(parts.join('.'));" "$CANDIDATE") || {
|
|
60
|
+
echo "Cannot auto-bump non x.y.z version: $CANDIDATE"
|
|
61
|
+
exit 1
|
|
62
|
+
}
|
|
63
|
+
done
|
|
64
|
+
TARGET_VERSION="$CANDIDATE"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
CHANGED=false
|
|
68
|
+
if [ "$TARGET_VERSION" != "$BASE_VERSION" ]; then
|
|
69
|
+
npm version "$TARGET_VERSION" --no-git-tag-version
|
|
70
|
+
CHANGED=true
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
echo "version=$TARGET_VERSION" >> "$GITHUB_OUTPUT"
|
|
74
|
+
echo "tag=v$TARGET_VERSION" >> "$GITHUB_OUTPUT"
|
|
75
|
+
echo "changed=$CHANGED" >> "$GITHUB_OUTPUT"
|
|
76
|
+
echo "mode=$MODE" >> "$GITHUB_OUTPUT"
|
|
77
|
+
|
|
78
|
+
- name: Ensure NPM token is configured
|
|
79
|
+
run: |
|
|
80
|
+
if [ -z "${NODE_AUTH_TOKEN}" ]; then
|
|
81
|
+
echo "Missing NODE_AUTH_TOKEN/NPM_TOKEN secret. Configure repository secret NPM_TOKEN."
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
env:
|
|
85
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
86
|
+
|
|
87
|
+
- name: Remove Python cache artifacts from workspace
|
|
88
|
+
run: |
|
|
89
|
+
find . -type d -name "__pycache__" -prune -exec rm -rf {} +
|
|
90
|
+
find . -type f -name "*.pyc" -delete
|
|
91
|
+
|
|
92
|
+
- name: Publish to npm
|
|
93
|
+
run: npm publish --access public
|
|
94
|
+
env:
|
|
95
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
96
|
+
|
|
97
|
+
- name: Sync package.json version to repository
|
|
98
|
+
if: steps.version.outputs.changed == 'true'
|
|
99
|
+
run: |
|
|
100
|
+
git config user.name "github-actions[bot]"
|
|
101
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
102
|
+
git add package.json
|
|
103
|
+
git commit -m "chore(release): sync npm version to ${{ steps.version.outputs.tag }} [skip ci]"
|
|
104
|
+
git push
|
|
105
|
+
|
|
106
|
+
- name: Create GitHub release
|
|
107
|
+
uses: softprops/action-gh-release@v2
|
|
108
|
+
with:
|
|
109
|
+
tag_name: ${{ steps.version.outputs.tag }}
|
|
110
|
+
name: ${{ steps.version.outputs.tag }}
|
|
111
|
+
generate_release_notes: true
|
package/FINAL_USAGE_GUIDE.md
CHANGED
|
@@ -85,6 +85,62 @@ Esto significa:
|
|
|
85
85
|
- las fuentes se conservan cuando sean obligatorias,
|
|
86
86
|
- el sistema solo aumenta detalle si el usuario o el caso lo requiere.
|
|
87
87
|
|
|
88
|
+
## 7. Telemetry Engine
|
|
89
|
+
|
|
90
|
+
El sistema incluye un engine de telemetría desacoplado con collector único.
|
|
91
|
+
|
|
92
|
+
Flujo:
|
|
93
|
+
|
|
94
|
+
```txt
|
|
95
|
+
Componente -> TelemetryCollector -> Pipeline -> Exporters
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Exporters soportados:
|
|
99
|
+
|
|
100
|
+
- `console` (siempre disponible)
|
|
101
|
+
- `json` (persistencia local en `.telemetry/`)
|
|
102
|
+
- `langsmith` (opcional, solo con configuración válida)
|
|
103
|
+
|
|
104
|
+
Si un exporter falla:
|
|
105
|
+
|
|
106
|
+
- se registra warning,
|
|
107
|
+
- los demás exporters continúan,
|
|
108
|
+
- la ejecución principal no se detiene.
|
|
109
|
+
|
|
110
|
+
### Configuración rápida
|
|
111
|
+
|
|
112
|
+
Archivo `telemetry/config.json`:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"telemetry": {
|
|
117
|
+
"enabled": true,
|
|
118
|
+
"batch_size": 25,
|
|
119
|
+
"telemetry_dir": ".telemetry",
|
|
120
|
+
"exporters": ["console", "json", "langsmith"]
|
|
121
|
+
},
|
|
122
|
+
"langsmith": {
|
|
123
|
+
"enabled": false,
|
|
124
|
+
"api_key": "",
|
|
125
|
+
"project": "",
|
|
126
|
+
"endpoint": ""
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Cómo activar LangSmith
|
|
132
|
+
|
|
133
|
+
1. Configurar `LANGSMITH_ENABLED=true`.
|
|
134
|
+
2. Definir `LANGSMITH_API_KEY` y `LANGSMITH_PROJECT`.
|
|
135
|
+
3. Mantener `langsmith` en `telemetry.exporters`.
|
|
136
|
+
|
|
137
|
+
Si falta configuración, se omite automáticamente.
|
|
138
|
+
|
|
139
|
+
### Cómo deshabilitar exporters
|
|
140
|
+
|
|
141
|
+
- Desactivar todo: `TELEMETRY_ENABLED=false`
|
|
142
|
+
- Solo algunos: `TELEMETRY_EXPORTERS=console,json`
|
|
143
|
+
|
|
88
144
|
## Diagrama Visual De Uso Diario
|
|
89
145
|
|
|
90
146
|
```mermaid
|
package/README.md
CHANGED
|
@@ -245,6 +245,139 @@ Artefactos canónicos:
|
|
|
245
245
|
|
|
246
246
|
## Observabilidad
|
|
247
247
|
|
|
248
|
+
### Telemetry Engine (desacoplado y extensible)
|
|
249
|
+
|
|
250
|
+
La observabilidad ahora se soporta mediante un engine propio en `telemetry/`.
|
|
251
|
+
|
|
252
|
+
Principios:
|
|
253
|
+
|
|
254
|
+
- Telemetría siempre activa a nivel de modelo de datos.
|
|
255
|
+
- Exporters opcionales (`console`, `json`, `langsmith`).
|
|
256
|
+
- Ningún flujo de negocio depende de LangSmith.
|
|
257
|
+
- Si un exporter falla, la ejecución principal continua.
|
|
258
|
+
|
|
259
|
+
Arquitectura:
|
|
260
|
+
|
|
261
|
+
```mermaid
|
|
262
|
+
flowchart TD
|
|
263
|
+
T[Tool/Flow] --> C[TelemetryCollector]
|
|
264
|
+
C --> P[Telemetry Pipeline]
|
|
265
|
+
P --> EX1[Console Exporter]
|
|
266
|
+
P --> EX2[JSON Exporter]
|
|
267
|
+
P --> EX3[LangSmith Exporter]
|
|
268
|
+
P --> EXN[Future Exporters]
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Trazas jerárquicas:
|
|
272
|
+
|
|
273
|
+
- Cada ejecución genera `execution_id`, `trace_id`, `span_id`, `parent_span_id`.
|
|
274
|
+
- Se propaga contexto con `contextvars` (sin variables globales).
|
|
275
|
+
- Spans soportan `events`, `status`, `duration_ms` y error asociado.
|
|
276
|
+
|
|
277
|
+
Configuración base (`telemetry/config.json`):
|
|
278
|
+
|
|
279
|
+
```json
|
|
280
|
+
{
|
|
281
|
+
"telemetry": {
|
|
282
|
+
"enabled": true,
|
|
283
|
+
"batch_size": 100,
|
|
284
|
+
"telemetry_dir": ".telemetry",
|
|
285
|
+
"exporters": ["console", "json"]
|
|
286
|
+
},
|
|
287
|
+
"langsmith": {
|
|
288
|
+
"enabled": false,
|
|
289
|
+
"api_key": "",
|
|
290
|
+
"project": "",
|
|
291
|
+
"endpoint": "",
|
|
292
|
+
"high_signal_only": true,
|
|
293
|
+
"min_span_duration_ms": 100,
|
|
294
|
+
"emit_execution_summary": true
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Conexión segura a LangSmith (sin subir token al repo/npm):
|
|
300
|
+
|
|
301
|
+
1. No guardes el token en `telemetry/config.json`.
|
|
302
|
+
2. Define variables de entorno locales (usuario o sesión).
|
|
303
|
+
3. Activa exporter por entorno con `TELEMETRY_EXPORTERS=console,json,langsmith`.
|
|
304
|
+
4. Verifica que `.env` y variantes están ignorados por Git y npm.
|
|
305
|
+
|
|
306
|
+
Ejemplo (PowerShell, solo sesión actual):
|
|
307
|
+
|
|
308
|
+
```powershell
|
|
309
|
+
$env:LANGSMITH_ENABLED='true'
|
|
310
|
+
$env:LANGSMITH_API_KEY='tu_token'
|
|
311
|
+
$env:LANGSMITH_PROJECT='mcpee-local'
|
|
312
|
+
$env:LANGSMITH_ENDPOINT='https://api.smith.langchain.com'
|
|
313
|
+
$env:LANGSMITH_HIGH_SIGNAL_ONLY='true'
|
|
314
|
+
$env:LANGSMITH_MIN_SPAN_DURATION_MS='100'
|
|
315
|
+
$env:LANGSMITH_EMIT_EXECUTION_SUMMARY='true'
|
|
316
|
+
$env:TELEMETRY_EXPORTERS='console,json,langsmith'
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Persistente para tu usuario Windows:
|
|
320
|
+
|
|
321
|
+
```powershell
|
|
322
|
+
[System.Environment]::SetEnvironmentVariable('LANGSMITH_ENABLED','true','User')
|
|
323
|
+
[System.Environment]::SetEnvironmentVariable('LANGSMITH_API_KEY','tu_token','User')
|
|
324
|
+
[System.Environment]::SetEnvironmentVariable('LANGSMITH_PROJECT','mcpee-local','User')
|
|
325
|
+
[System.Environment]::SetEnvironmentVariable('LANGSMITH_ENDPOINT','https://api.smith.langchain.com','User')
|
|
326
|
+
[System.Environment]::SetEnvironmentVariable('LANGSMITH_HIGH_SIGNAL_ONLY','true','User')
|
|
327
|
+
[System.Environment]::SetEnvironmentVariable('LANGSMITH_MIN_SPAN_DURATION_MS','100','User')
|
|
328
|
+
[System.Environment]::SetEnvironmentVariable('LANGSMITH_EMIT_EXECUTION_SUMMARY','true','User')
|
|
329
|
+
[System.Environment]::SetEnvironmentVariable('TELEMETRY_EXPORTERS','console,json,langsmith','User')
|
|
330
|
+
|
|
331
|
+
Modo high-signal recomendado en LangSmith:
|
|
332
|
+
|
|
333
|
+
- `LANGSMITH_HIGH_SIGNAL_ONLY=true` (default): prioriza trazas útiles y reduce ruido.
|
|
334
|
+
- `LANGSMITH_MIN_SPAN_DURATION_MS=100` (default): solo mantiene spans rápidos cuando fallan; los de éxito deben superar el umbral.
|
|
335
|
+
- `LANGSMITH_EMIT_EXECUTION_SUMMARY=true` (default): añade un resumen consolidado por ejecución (duración, estado, warnings/errors, tokens/coste).
|
|
336
|
+
- Mantiene eventos clave (`ExecutionStarted`, `ExecutionFinished`, `RoutingResolved`, warnings/errores) y resumen `UsageSummary` con modelo/tokens/coste.
|
|
337
|
+
- Omite eventos de bajo valor para la UI de LangSmith, pero conserva debug detallado en exporters locales (`console`, `json`).
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Para volver al modo local sin LangSmith:
|
|
341
|
+
|
|
342
|
+
```powershell
|
|
343
|
+
$env:LANGSMITH_ENABLED='false'
|
|
344
|
+
$env:TELEMETRY_EXPORTERS='console,json'
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Variables de entorno soportadas:
|
|
348
|
+
|
|
349
|
+
- `TELEMETRY_ENABLED`
|
|
350
|
+
- `TELEMETRY_EXPORTERS`
|
|
351
|
+
- `TELEMETRY_BATCH_SIZE`
|
|
352
|
+
- `TELEMETRY_DIR`
|
|
353
|
+
- `LANGSMITH_ENABLED`
|
|
354
|
+
- `LANGSMITH_API_KEY`
|
|
355
|
+
- `LANGSMITH_PROJECT`
|
|
356
|
+
- `LANGSMITH_ENDPOINT`
|
|
357
|
+
- `LANGSMITH_WORKSPACE_ID` (opcional, recomendado para cuentas con multiples workspaces)
|
|
358
|
+
|
|
359
|
+
Nota: el engine carga automáticamente `.env` en la raíz del repo. Si también existe variable en el entorno del sistema/proceso, esa tiene prioridad.
|
|
360
|
+
|
|
361
|
+
Dependencia runtime: `langsmith` está incluida en `requirements.txt` para que `scripts/setup/setup-prerequisites.ps1` la instale automáticamente cuando prepares el entorno Python.
|
|
362
|
+
|
|
363
|
+
Cómo crear un exporter nuevo:
|
|
364
|
+
|
|
365
|
+
1. Implementar contrato `export/flush/shutdown` en `telemetry/exporters/<nuevo>/exporter.py`.
|
|
366
|
+
2. Registrar el exporter en `telemetry/bootstrap.py`.
|
|
367
|
+
3. Añadirlo en `telemetry/config.json` o `TELEMETRY_EXPORTERS`.
|
|
368
|
+
|
|
369
|
+
Si LangSmith no está configurado correctamente, el exporter se omite y el engine sigue funcionando con `console/json`.
|
|
370
|
+
|
|
371
|
+
Benchmark de overhead on/off:
|
|
372
|
+
|
|
373
|
+
```powershell
|
|
374
|
+
py -3 .\scripts\ops\telemetry-benchmark.py --iterations 10
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Salida:
|
|
378
|
+
|
|
379
|
+
- `observability/evals/telemetry-overhead-benchmark.json`
|
|
380
|
+
|
|
248
381
|
Registros principales:
|
|
249
382
|
|
|
250
383
|
- `observability/logs/routing-decisions.jsonl`
|
package/autodocs/README.md
CHANGED
|
@@ -14,6 +14,12 @@ AutoDocs es la wiki interna nativa de `mcp-efficiency-engine`.
|
|
|
14
14
|
py -3 -m scripts.wiki.wiki_compiler
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
## Sincronizacion automatica
|
|
18
|
+
|
|
19
|
+
- En CI, el workflow `autodocs-sync` valida en PR y sincroniza en `main`/`develop`.
|
|
20
|
+
- La ejecucion ya no depende de filtros de path: cualquier cambio potencialmente relevante recompila AutoDocs.
|
|
21
|
+
- Si hay drift, CI exige regenerar y commitear `autodocs/generated` y `autodocs/site`.
|
|
22
|
+
|
|
17
23
|
## Artefactos clave
|
|
18
24
|
|
|
19
25
|
- `autodocs/generated/unified-graph.json`
|
package/observability/metrics.md
CHANGED
|
@@ -28,6 +28,39 @@ Métricas: routing accuracy, tool usage, tool misuse, tool switching, grounding
|
|
|
28
28
|
- token_efficiency: tendencia estable o mejorando
|
|
29
29
|
- caveman_effectiveness: `>= 85%`
|
|
30
30
|
|
|
31
|
+
## Telemetry Engine native metrics
|
|
32
|
+
|
|
33
|
+
El engine expone métricas propias y no depende de proveedores externos:
|
|
34
|
+
|
|
35
|
+
- execution_time_ms
|
|
36
|
+
- tool_duration_ms
|
|
37
|
+
- average_duration_ms
|
|
38
|
+
- parallel_tasks
|
|
39
|
+
- sequential_tasks
|
|
40
|
+
- retry_count
|
|
41
|
+
- error_count
|
|
42
|
+
- warning_count
|
|
43
|
+
- llm_calls
|
|
44
|
+
- provider_calls
|
|
45
|
+
- mcp_calls
|
|
46
|
+
- tool_invocations
|
|
47
|
+
- tokens_input
|
|
48
|
+
- tokens_output
|
|
49
|
+
- total_tokens
|
|
50
|
+
- estimated_cost
|
|
51
|
+
- cache_hits
|
|
52
|
+
- cache_misses
|
|
53
|
+
- compression_ratio
|
|
54
|
+
- parallel_efficiency
|
|
55
|
+
- prompt_reduction
|
|
56
|
+
- context_reduction
|
|
57
|
+
- efficiency_score (0-100)
|
|
58
|
+
|
|
59
|
+
Los cálculos viven en:
|
|
60
|
+
|
|
61
|
+
- `telemetry/metrics/aggregator.py`
|
|
62
|
+
- `telemetry/scoring/efficiency.py`
|
|
63
|
+
|
|
31
64
|
## Semaforo
|
|
32
65
|
|
|
33
66
|
- `OK`: todos los umbrales en rango.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Scoring Rubric
|
|
2
2
|
|
|
3
|
+
> El score de eficiencia es nativo del Telemetry Engine y no depende de LangSmith.
|
|
4
|
+
|
|
3
5
|
## Componentes y pesos
|
|
4
6
|
|
|
5
7
|
- Routing score: 40%
|
|
@@ -36,3 +38,21 @@
|
|
|
36
38
|
- `80-89`: Aceptable
|
|
37
39
|
- `70-79`: Mejorable
|
|
38
40
|
- `< 70`: No apto
|
|
41
|
+
|
|
42
|
+
## Efficiency Score (Telemetry Engine)
|
|
43
|
+
|
|
44
|
+
Salida: `0..100`.
|
|
45
|
+
|
|
46
|
+
Factores por defecto:
|
|
47
|
+
|
|
48
|
+
- time
|
|
49
|
+
- cost
|
|
50
|
+
- tokens
|
|
51
|
+
- cache
|
|
52
|
+
- parallelism
|
|
53
|
+
- reuse
|
|
54
|
+
- calls
|
|
55
|
+
- compression
|
|
56
|
+
|
|
57
|
+
Implementación base en `telemetry/scoring/efficiency.py`.
|
|
58
|
+
Los pesos son configurables y el algoritmo se puede ajustar sin tocar exporters.
|
|
@@ -11,12 +11,21 @@ SECTIONS = section_catalog()
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class GraphConsolidator:
|
|
14
|
-
def __init__(self, output_graph_path: Path, markdown_output_dir: Path) -> None:
|
|
14
|
+
def __init__(self, output_graph_path: Path, markdown_output_dir: Path, telemetry_collector: Any | None = None) -> None:
|
|
15
15
|
self.output_graph_path = output_graph_path
|
|
16
16
|
self.markdown_output_dir = markdown_output_dir
|
|
17
17
|
self.generated_output_dir = output_graph_path.parent
|
|
18
|
+
self._telemetry = telemetry_collector
|
|
18
19
|
|
|
19
20
|
def consolidate(self, provider_contracts: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
21
|
+
if self._telemetry is not None:
|
|
22
|
+
self._telemetry.record_event(
|
|
23
|
+
"KnowledgeGenerated",
|
|
24
|
+
{
|
|
25
|
+
"operation": "graph_consolidate_start",
|
|
26
|
+
"provider_contracts": len(provider_contracts),
|
|
27
|
+
},
|
|
28
|
+
)
|
|
20
29
|
raw_nodes: Dict[str, Dict[str, Any]] = {}
|
|
21
30
|
wiki_nodes: Dict[str, Dict[str, Any]] = {}
|
|
22
31
|
for contract in provider_contracts:
|
|
@@ -54,6 +63,17 @@ class GraphConsolidator:
|
|
|
54
63
|
relations_index = self._build_relations_index(wiki_nodes)
|
|
55
64
|
section_manifest = self._build_section_manifest(wiki_nodes)
|
|
56
65
|
|
|
66
|
+
if self._telemetry is not None:
|
|
67
|
+
self._telemetry.record_metric("tool_invocations", float(len(provider_contracts)), unit="count")
|
|
68
|
+
self._telemetry.record_metric("cache_misses", 0.0, unit="count")
|
|
69
|
+
self._telemetry.record_event(
|
|
70
|
+
"KnowledgeGenerated",
|
|
71
|
+
{
|
|
72
|
+
"operation": "graph_consolidate_finish",
|
|
73
|
+
"nodes": len(wiki_nodes),
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
|
|
57
77
|
return {
|
|
58
78
|
"last_updated": self._deterministic_marker(wiki_nodes),
|
|
59
79
|
"nodes": wiki_nodes,
|
|
@@ -71,11 +91,23 @@ class GraphConsolidator:
|
|
|
71
91
|
return f"sha256:{digest}"
|
|
72
92
|
|
|
73
93
|
def persist_graph(self, unified_graph: Dict[str, Any]) -> None:
|
|
94
|
+
if self._telemetry is not None:
|
|
95
|
+
self._telemetry.record_event("ToolStarted", {"tool": "persist_graph"})
|
|
74
96
|
self.output_graph_path.parent.mkdir(parents=True, exist_ok=True)
|
|
75
97
|
with self.output_graph_path.open("w", encoding="utf-8") as handle:
|
|
76
98
|
json.dump(unified_graph, handle, indent=2, ensure_ascii=True)
|
|
99
|
+
if self._telemetry is not None:
|
|
100
|
+
self._telemetry.record_event(
|
|
101
|
+
"ToolFinished",
|
|
102
|
+
{
|
|
103
|
+
"tool": "persist_graph",
|
|
104
|
+
"path": str(self.output_graph_path),
|
|
105
|
+
},
|
|
106
|
+
)
|
|
77
107
|
|
|
78
108
|
def persist_manifests(self, unified_graph: Dict[str, Any]) -> Dict[str, int]:
|
|
109
|
+
if self._telemetry is not None:
|
|
110
|
+
self._telemetry.record_event("ToolStarted", {"tool": "persist_manifests"})
|
|
79
111
|
self.generated_output_dir.mkdir(parents=True, exist_ok=True)
|
|
80
112
|
artifacts = {
|
|
81
113
|
"search-index.json": unified_graph.get("search_index", []),
|
|
@@ -87,6 +119,14 @@ class GraphConsolidator:
|
|
|
87
119
|
output_path = self.generated_output_dir / file_name
|
|
88
120
|
with output_path.open("w", encoding="utf-8") as handle:
|
|
89
121
|
json.dump(payload, handle, indent=2, ensure_ascii=True)
|
|
122
|
+
if self._telemetry is not None:
|
|
123
|
+
self._telemetry.record_event(
|
|
124
|
+
"ToolFinished",
|
|
125
|
+
{
|
|
126
|
+
"tool": "persist_manifests",
|
|
127
|
+
"manifests": len(artifacts),
|
|
128
|
+
},
|
|
129
|
+
)
|
|
90
130
|
return {"manifests": len(artifacts)}
|
|
91
131
|
|
|
92
132
|
def project_dirty_nodes(
|
|
@@ -96,6 +136,15 @@ class GraphConsolidator:
|
|
|
96
136
|
all_nodes: Dict[str, Dict[str, Any]],
|
|
97
137
|
cached_nodes: Dict[str, Dict[str, Any]],
|
|
98
138
|
) -> Dict[str, int]:
|
|
139
|
+
if self._telemetry is not None:
|
|
140
|
+
self._telemetry.record_event(
|
|
141
|
+
"ToolStarted",
|
|
142
|
+
{
|
|
143
|
+
"tool": "project_dirty_nodes",
|
|
144
|
+
"dirty_nodes": len(dirty_nodes),
|
|
145
|
+
"deleted_nodes": len(deleted_nodes),
|
|
146
|
+
},
|
|
147
|
+
)
|
|
99
148
|
self.markdown_output_dir.mkdir(parents=True, exist_ok=True)
|
|
100
149
|
|
|
101
150
|
rendered = 0
|
|
@@ -124,6 +173,16 @@ class GraphConsolidator:
|
|
|
124
173
|
deleted += 1
|
|
125
174
|
|
|
126
175
|
indexes = self._render_index_pages(all_nodes)
|
|
176
|
+
if self._telemetry is not None:
|
|
177
|
+
self._telemetry.record_event(
|
|
178
|
+
"ToolFinished",
|
|
179
|
+
{
|
|
180
|
+
"tool": "project_dirty_nodes",
|
|
181
|
+
"rendered": rendered,
|
|
182
|
+
"deleted": deleted,
|
|
183
|
+
"indexes": indexes,
|
|
184
|
+
},
|
|
185
|
+
)
|
|
127
186
|
return {
|
|
128
187
|
"rendered": rendered,
|
|
129
188
|
"deleted": deleted,
|
|
@@ -4,8 +4,9 @@ from typing import Any, Dict
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class IncrementalEngine:
|
|
7
|
-
def __init__(self, cache_path: Path) -> None:
|
|
7
|
+
def __init__(self, cache_path: Path, telemetry_collector: Any | None = None) -> None:
|
|
8
8
|
self.cache_path = cache_path
|
|
9
|
+
self._telemetry = telemetry_collector
|
|
9
10
|
|
|
10
11
|
def _extract_nodes(self, loaded: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
|
|
11
12
|
preferred = loaded.get("wiki_nodes")
|
|
@@ -37,6 +38,14 @@ class IncrementalEngine:
|
|
|
37
38
|
return {"last_updated": "", "nodes": {}}
|
|
38
39
|
|
|
39
40
|
def diff(self, incoming_nodes: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
|
|
41
|
+
if self._telemetry is not None:
|
|
42
|
+
self._telemetry.record_event(
|
|
43
|
+
"ToolStarted",
|
|
44
|
+
{
|
|
45
|
+
"tool": "incremental_diff",
|
|
46
|
+
"incoming_nodes": len(incoming_nodes),
|
|
47
|
+
},
|
|
48
|
+
)
|
|
40
49
|
cached = self._load_cached_graph()
|
|
41
50
|
cached_nodes = cached.get("nodes", {})
|
|
42
51
|
|
|
@@ -50,6 +59,19 @@ class IncrementalEngine:
|
|
|
50
59
|
dirty_nodes[node_key] = incoming
|
|
51
60
|
|
|
52
61
|
deleted_nodes = [key for key in cached_nodes.keys() if key not in incoming_nodes]
|
|
62
|
+
if self._telemetry is not None:
|
|
63
|
+
cache_hits = max(0, len(incoming_nodes) - len(dirty_nodes))
|
|
64
|
+
cache_misses = len(dirty_nodes)
|
|
65
|
+
self._telemetry.record_event(
|
|
66
|
+
"ToolFinished",
|
|
67
|
+
{
|
|
68
|
+
"tool": "incremental_diff",
|
|
69
|
+
"dirty_nodes": len(dirty_nodes),
|
|
70
|
+
"deleted_nodes": len(deleted_nodes),
|
|
71
|
+
},
|
|
72
|
+
)
|
|
73
|
+
self._telemetry.record_metric("cache_hits", float(cache_hits), unit="count")
|
|
74
|
+
self._telemetry.record_metric("cache_misses", float(cache_misses), unit="count")
|
|
53
75
|
return {
|
|
54
76
|
"dirty_nodes": dirty_nodes,
|
|
55
77
|
"deleted_nodes": deleted_nodes,
|