@unerr-ai/unerr 0.2.0 → 0.2.2
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/README.md +6 -0
- package/dist/cli.js +37236 -35793
- package/package.json +6 -1
- package/dist/behaviors/agent-llm-bridge.js +0 -166
- package/dist/behaviors/architecture-guard.js +0 -256
- package/dist/behaviors/auto-doc.js +0 -247
- package/dist/behaviors/cascade-guard.js +0 -289
- package/dist/behaviors/change-narrative.js +0 -270
- package/dist/behaviors/convention-drift.js +0 -290
- package/dist/behaviors/framework.js +0 -235
- package/dist/behaviors/guard-formatter.js +0 -44
- package/dist/behaviors/incomplete-work.js +0 -270
- package/dist/behaviors/loop-breaker.js +0 -300
- package/dist/behaviors/session-continuity.js +0 -208
- package/dist/commands/branches.js +0 -97
- package/dist/commands/check-commit.js +0 -225
- package/dist/commands/compress-output.js +0 -64
- package/dist/commands/config-verify.js +0 -243
- package/dist/commands/daemon.js +0 -905
- package/dist/commands/dashboard.js +0 -52
- package/dist/commands/debug.js +0 -200
- package/dist/commands/enrich.js +0 -184
- package/dist/commands/exec.js +0 -233
- package/dist/commands/gain.js +0 -156
- package/dist/commands/hook.js +0 -88
- package/dist/commands/index.js +0 -88
- package/dist/commands/init.js +0 -74
- package/dist/commands/install.js +0 -505
- package/dist/commands/learn.js +0 -116
- package/dist/commands/manifest.js +0 -193
- package/dist/commands/rewind.js +0 -103
- package/dist/commands/serve.js +0 -19
- package/dist/commands/setup-wizard.js +0 -414
- package/dist/commands/skills.js +0 -64
- package/dist/commands/stats.js +0 -20
- package/dist/commands/status.js +0 -654
- package/dist/commands/timeline.js +0 -139
- package/dist/commands/uninstall.js +0 -230
- package/dist/components/App.js +0 -109
- package/dist/components/Banner.js +0 -12
- package/dist/components/ConfirmPrompt.js +0 -25
- package/dist/components/DriftSummary.js +0 -23
- package/dist/components/GradeBadge.js +0 -15
- package/dist/components/HealthCard.js +0 -18
- package/dist/components/InkSpinner.js +0 -22
- package/dist/components/InputBox.js +0 -17
- package/dist/components/KeyValue.js +0 -13
- package/dist/components/MessageList.js +0 -14
- package/dist/components/ProgressBar.js +0 -26
- package/dist/components/Section.js +0 -16
- package/dist/components/SessionSummaryCard.js +0 -73
- package/dist/components/StartupDisplay.js +0 -24
- package/dist/components/StatusDashboard.js +0 -57
- package/dist/components/StatusLine.js +0 -8
- package/dist/components/StepLine.js +0 -22
- package/dist/components/Theme.js +0 -20
- package/dist/components/ToolProgress.js +0 -8
- package/dist/components/ViolationList.js +0 -21
- package/dist/components/render.js +0 -13
- package/dist/config/agent-registry.js +0 -237
- package/dist/config/claude-settings-hooks.js +0 -304
- package/dist/config/hook-installer.js +0 -65
- package/dist/config/instruction-writer.js +0 -388
- package/dist/config/mcp-config-writer.js +0 -266
- package/dist/config/settings.js +0 -174
- package/dist/config/tool-detector.js +0 -42
- package/dist/config/value-surfacing.js +0 -119
- package/dist/core/context-assembly.js +0 -108
- package/dist/core/conversation.js +0 -33
- package/dist/core/local-chat-provider.js +0 -475
- package/dist/core/provider-factory.js +0 -55
- package/dist/core/providers.js +0 -90
- package/dist/core/query-engine.js +0 -174
- package/dist/daemon/api.js +0 -312
- package/dist/daemon/autostart.js +0 -119
- package/dist/daemon/bootstrap.js +0 -39
- package/dist/daemon/client.js +0 -164
- package/dist/daemon/detect-ci.js +0 -81
- package/dist/daemon/platform-linux.js +0 -146
- package/dist/daemon/platform-macos.js +0 -134
- package/dist/daemon/platform-windows.js +0 -116
- package/dist/daemon/process-manager.js +0 -299
- package/dist/daemon/protocol.js +0 -23
- package/dist/daemon/registry.js +0 -270
- package/dist/daemon/settings-schema.js +0 -72
- package/dist/daemon/system-health.js +0 -134
- package/dist/daemon/version-checker.js +0 -262
- package/dist/daemon/warm-start.js +0 -223
- package/dist/entrypoints/cli.js +0 -1043
- package/dist/entrypoints/daemon.js +0 -380
- package/dist/entrypoints/repl.js +0 -147
- package/dist/hooks/adapters/claude-code.js +0 -90
- package/dist/hooks/adapters/cline.js +0 -100
- package/dist/hooks/adapters/cursor.js +0 -98
- package/dist/hooks/hook-dedup.js +0 -79
- package/dist/hooks/hook-runner.js +0 -113
- package/dist/hooks/navigation-hooks.js +0 -175
- package/dist/hooks/prompt-hooks.js +0 -63
- package/dist/hooks/shell-hooks.js +0 -47
- package/dist/ignore.js +0 -111
- package/dist/intelligence/approach-suggester.js +0 -61
- package/dist/intelligence/ast-extractor.js +0 -2615
- package/dist/intelligence/ast-worker.js +0 -34
- package/dist/intelligence/background-indexer.js +0 -121
- package/dist/intelligence/blast-radius.js +0 -200
- package/dist/intelligence/community-detection.js +0 -691
- package/dist/intelligence/community-detector.js +0 -184
- package/dist/intelligence/computation-scheduler.js +0 -75
- package/dist/intelligence/confidence-propagation.js +0 -47
- package/dist/intelligence/convention-detector.js +0 -242
- package/dist/intelligence/convention-learner.js +0 -205
- package/dist/intelligence/convention-matcher.js +0 -205
- package/dist/intelligence/cozo-schema.js +0 -376
- package/dist/intelligence/decision-point-detector.js +0 -90
- package/dist/intelligence/deep-dive-tools.js +0 -586
- package/dist/intelligence/durability-scorer.js +0 -84
- package/dist/intelligence/exploration-cost.js +0 -204
- package/dist/intelligence/exploration-pattern-tracker.js +0 -61
- package/dist/intelligence/fact-generator.js +0 -322
- package/dist/intelligence/facts-schema.js +0 -90
- package/dist/intelligence/file-intelligence.js +0 -59
- package/dist/intelligence/graph-holder.js +0 -220
- package/dist/intelligence/graph-temporal-joiner.js +0 -238
- package/dist/intelligence/health-grade.js +0 -423
- package/dist/intelligence/health-grader.js +0 -200
- package/dist/intelligence/health-map-data.js +0 -259
- package/dist/intelligence/import-symbols.js +0 -136
- package/dist/intelligence/incremental-indexer.js +0 -658
- package/dist/intelligence/indexer/centrality.js +0 -62
- package/dist/intelligence/indexer/cfg-context.js +0 -95
- package/dist/intelligence/indexer/confidence.js +0 -34
- package/dist/intelligence/indexer/cross-file-resolver.js +0 -104
- package/dist/intelligence/indexer/edge-repair.js +0 -89
- package/dist/intelligence/indexer/entity-key.js +0 -17
- package/dist/intelligence/indexer/export-map.js +0 -132
- package/dist/intelligence/indexer/git-cochange.js +0 -128
- package/dist/intelligence/indexer/graph-patch.js +0 -147
- package/dist/intelligence/indexer/incremental.js +0 -78
- package/dist/intelligence/indexer/ingest.js +0 -160
- package/dist/intelligence/indexer/language-detect.js +0 -226
- package/dist/intelligence/indexer/metadata.js +0 -63
- package/dist/intelligence/indexer/mutation-tracker.js +0 -79
- package/dist/intelligence/indexer/orchestrator.js +0 -155
- package/dist/intelligence/indexer/plugin-interface.js +0 -31
- package/dist/intelligence/indexer/plugins/csharp.js +0 -440
- package/dist/intelligence/indexer/plugins/go.js +0 -335
- package/dist/intelligence/indexer/plugins/java.js +0 -370
- package/dist/intelligence/indexer/plugins/python.js +0 -358
- package/dist/intelligence/indexer/plugins/regex-fallback.js +0 -82
- package/dist/intelligence/indexer/plugins/ruby.js +0 -290
- package/dist/intelligence/indexer/plugins/rust.js +0 -484
- package/dist/intelligence/indexer/plugins/tier2-generic.js +0 -310
- package/dist/intelligence/indexer/plugins/typescript.js +0 -456
- package/dist/intelligence/indexer/resource-monitor.js +0 -93
- package/dist/intelligence/indexer/scip/decoder.js +0 -253
- package/dist/intelligence/indexer/scip/detector.js +0 -232
- package/dist/intelligence/indexer/scip/downloader.js +0 -427
- package/dist/intelligence/indexer/scip/fallback.js +0 -34
- package/dist/intelligence/indexer/scip/merger.js +0 -109
- package/dist/intelligence/indexer/scip/orchestrator.js +0 -433
- package/dist/intelligence/indexer/scip/runner.js +0 -98
- package/dist/intelligence/indexer/snapshot.js +0 -66
- package/dist/intelligence/indexer/test-detector.js +0 -196
- package/dist/intelligence/indexer/watch-integration.js +0 -61
- package/dist/intelligence/indexer/worker.js +0 -85
- package/dist/intelligence/local-convention-detector.js +0 -437
- package/dist/intelligence/local-embeddings.js +0 -190
- package/dist/intelligence/local-graph.js +0 -1946
- package/dist/intelligence/local-indexer.js +0 -1575
- package/dist/intelligence/local-llm.js +0 -163
- package/dist/intelligence/local-rule-generator.js +0 -154
- package/dist/intelligence/local-snapshot.js +0 -213
- package/dist/intelligence/negative-knowledge.js +0 -103
- package/dist/intelligence/persistent-db.js +0 -85
- package/dist/intelligence/query-router.js +0 -2556
- package/dist/intelligence/risk-classifier.js +0 -116
- package/dist/intelligence/rule-evaluator.js +0 -380
- package/dist/intelligence/rule-generator.js +0 -49
- package/dist/intelligence/search-index.js +0 -173
- package/dist/intelligence/semantic/docstring-extractor.js +0 -67
- package/dist/intelligence/semantic/embedding-store.js +0 -52
- package/dist/intelligence/semantic/enrichment-orchestrator.js +0 -48
- package/dist/intelligence/semantic/git-message-miner.js +0 -114
- package/dist/intelligence/semantic/identifier-tokenizer.js +0 -51
- package/dist/intelligence/semantic/node2vec-embeddings.js +0 -71
- package/dist/intelligence/semantic/node2vec-walks.js +0 -103
- package/dist/intelligence/semantic/path-domain-inference.js +0 -112
- package/dist/intelligence/semantic/similarity-engine.js +0 -60
- package/dist/intelligence/semantic/tfidf-vectors.js +0 -88
- package/dist/intelligence/session-brief-builder.js +0 -159
- package/dist/intelligence/session-context.js +0 -221
- package/dist/intelligence/session-health-monitor.js +0 -211
- package/dist/intelligence/session-narrative.js +0 -197
- package/dist/intelligence/session-pattern-analyzer.js +0 -218
- package/dist/intelligence/signal-scorer.js +0 -390
- package/dist/intelligence/signal-show-store.js +0 -182
- package/dist/intelligence/smart-truncate.js +0 -158
- package/dist/intelligence/subgraph-cache.js +0 -88
- package/dist/intelligence/temporal-facts.js +0 -494
- package/dist/intelligence/token-estimator.js +0 -100
- package/dist/intelligence/tool-injector.js +0 -87
- package/dist/intelligence/tree-sitter-loader.js +0 -71
- package/dist/intelligence/worker-pool.js +0 -116
- package/dist/proxy/arg-validator.js +0 -79
- package/dist/proxy/auto-bootstrap.js +0 -167
- package/dist/proxy/bridge.js +0 -147
- package/dist/proxy/budget-enforcer.js +0 -70
- package/dist/proxy/compression-quality-monitor.js +0 -160
- package/dist/proxy/compression-stats.js +0 -51
- package/dist/proxy/context-rot-detector.js +0 -137
- package/dist/proxy/drift-detector.js +0 -139
- package/dist/proxy/efficiency-tracker.js +0 -79
- package/dist/proxy/fact-ranking.js +0 -154
- package/dist/proxy/format-encoder.js +0 -266
- package/dist/proxy/http-transport.js +0 -90
- package/dist/proxy/lifecycle-actor.js +0 -55
- package/dist/proxy/lifecycle-machine.js +0 -187
- package/dist/proxy/log-tailer.js +0 -265
- package/dist/proxy/model-pricing.js +0 -98
- package/dist/proxy/network-firewall.js +0 -141
- package/dist/proxy/nudge-state.js +0 -93
- package/dist/proxy/output-compressor.js +0 -185
- package/dist/proxy/pid-lock.js +0 -291
- package/dist/proxy/proxy-context.js +0 -11
- package/dist/proxy/proxy.js +0 -2633
- package/dist/proxy/response-enrichment.js +0 -32
- package/dist/proxy/response-envelope.js +0 -313
- package/dist/proxy/session-dedup.js +0 -82
- package/dist/proxy/session-legend.js +0 -30
- package/dist/proxy/session-persistence.js +0 -210
- package/dist/proxy/session-resume.js +0 -94
- package/dist/proxy/session-stats.js +0 -513
- package/dist/proxy/shell-classifier.js +0 -1346
- package/dist/proxy/shell-compression-log.js +0 -93
- package/dist/proxy/shell-compressor.js +0 -390
- package/dist/proxy/shell-graph-boost.js +0 -202
- package/dist/proxy/shell-monitor-map.js +0 -18
- package/dist/proxy/shell-stats.js +0 -54
- package/dist/proxy/shell-strategies/cloud.js +0 -215
- package/dist/proxy/shell-strategies/diff.js +0 -159
- package/dist/proxy/shell-strategies/error-diagnostic.js +0 -796
- package/dist/proxy/shell-strategies/filter-dsl.js +0 -358
- package/dist/proxy/shell-strategies/git-status.js +0 -177
- package/dist/proxy/shell-strategies/key-value.js +0 -193
- package/dist/proxy/shell-strategies/log-text.js +0 -154
- package/dist/proxy/shell-strategies/omni.js +0 -188
- package/dist/proxy/shell-strategies/progress.js +0 -55
- package/dist/proxy/shell-strategies/redact.js +0 -76
- package/dist/proxy/shell-strategies/structured.js +0 -241
- package/dist/proxy/shell-strategies/tabular.js +0 -243
- package/dist/proxy/shell-strategies/test-results-types.js +0 -13
- package/dist/proxy/shell-strategies/test-results.js +0 -784
- package/dist/proxy/shell-strategies/tree-paths.js +0 -144
- package/dist/proxy/shell-strategies/yaml.js +0 -182
- package/dist/proxy/shell-tee.js +0 -111
- package/dist/proxy/signal-dedup.js +0 -171
- package/dist/proxy/startup-renderer.js +0 -158
- package/dist/proxy/task-token-display.js +0 -38
- package/dist/proxy/token-counter.js +0 -61
- package/dist/proxy/tool-clusters.js +0 -273
- package/dist/proxy/tool-definitions.js +0 -525
- package/dist/proxy/transport-mux.js +0 -229
- package/dist/proxy/wire-cap.js +0 -268
- package/dist/rules/developer.mozilla.org.json +0 -9
- package/dist/rules/github.com.json +0 -21
- package/dist/schemas/api/skills.js +0 -19
- package/dist/schemas/common/errors.js +0 -7
- package/dist/schemas/common/headers.js +0 -5
- package/dist/schemas/entities/edge.js +0 -25
- package/dist/schemas/entities/entity.js +0 -22
- package/dist/schemas/entities/rule.js +0 -18
- package/dist/schemas/index.js +0 -14
- package/dist/server/event-bus.js +0 -59
- package/dist/server/http.js +0 -156
- package/dist/server/middleware.js +0 -70
- package/dist/server/routes/drift.js +0 -97
- package/dist/server/routes/intelligence.js +0 -1217
- package/dist/server/routes/reasoning-quality.js +0 -444
- package/dist/server/routes/session.js +0 -86
- package/dist/server/routes/stream.js +0 -120
- package/dist/server/routes/system.js +0 -73
- package/dist/server/routes/temporal.js +0 -170
- package/dist/server/routes/timeline.js +0 -232
- package/dist/server/routes/token-flow.js +0 -403
- package/dist/skills/effectiveness-tracker.js +0 -93
- package/dist/skills/local-pack.js +0 -380
- package/dist/skills/resolver.js +0 -495
- package/dist/state-detector.js +0 -83
- package/dist/timeline/intent-detector.js +0 -263
- package/dist/timeline/loop-miner.js +0 -140
- package/dist/timeline/open-threads.js +0 -49
- package/dist/timeline/signal-reinforcer.js +0 -62
- package/dist/timeline/timeline-bootstrap.js +0 -151
- package/dist/timeline/timeline-store.js +0 -618
- package/dist/tools/coding/bash.js +0 -49
- package/dist/tools/coding/file-edit.js +0 -72
- package/dist/tools/coding/file-outline.js +0 -227
- package/dist/tools/coding/file-read-protocol.js +0 -425
- package/dist/tools/coding/file-read.js +0 -35
- package/dist/tools/coding/file-write.js +0 -43
- package/dist/tools/coding/glob-tool.js +0 -109
- package/dist/tools/coding/grep.js +0 -162
- package/dist/tools/coding/index.js +0 -27
- package/dist/tools/intelligence/index.js +0 -269
- package/dist/tools/intelligence/record-fact.js +0 -48
- package/dist/tools/intelligence/timeline-markers.js +0 -130
- package/dist/tools/registry.js +0 -47
- package/dist/tools/types.js +0 -8
- package/dist/tracking/auto-snapshot-triggers.js +0 -246
- package/dist/tracking/branch-context.js +0 -115
- package/dist/tracking/branch-snapshot.js +0 -217
- package/dist/tracking/causal-bridge.js +0 -317
- package/dist/tracking/circuit-breaker.js +0 -147
- package/dist/tracking/commit-watcher.js +0 -114
- package/dist/tracking/context-ledger.js +0 -119
- package/dist/tracking/correction-detector.js +0 -324
- package/dist/tracking/drift-tracker.js +0 -874
- package/dist/tracking/durability-tracker.js +0 -94
- package/dist/tracking/entity-rewind.js +0 -200
- package/dist/tracking/file-hash-state.js +0 -114
- package/dist/tracking/git-attribution.js +0 -132
- package/dist/tracking/git-trailers.js +0 -171
- package/dist/tracking/intelligence-counter.js +0 -46
- package/dist/tracking/intent-correlator.js +0 -202
- package/dist/tracking/intent-encoder.js +0 -52
- package/dist/tracking/intent-token-tracker.js +0 -159
- package/dist/tracking/ledger-archiver.js +0 -94
- package/dist/tracking/ledger-chains.js +0 -245
- package/dist/tracking/metrics-store.js +0 -361
- package/dist/tracking/native-watcher.js +0 -131
- package/dist/tracking/offline-rewind.js +0 -295
- package/dist/tracking/pending-violations.js +0 -74
- package/dist/tracking/persistence-effectiveness.js +0 -167
- package/dist/tracking/prompt-durability.js +0 -202
- package/dist/tracking/quality-signals.js +0 -213
- package/dist/tracking/redactor.js +0 -73
- package/dist/tracking/rewind-engine.js +0 -161
- package/dist/tracking/session-history.js +0 -128
- package/dist/tracking/session-receipt.js +0 -88
- package/dist/tracking/session-summary-writer.js +0 -157
- package/dist/tracking/shadow-ledger.js +0 -321
- package/dist/tracking/stash-manager.js +0 -258
- package/dist/tracking/timeline-fork.js +0 -213
- package/dist/tracking/timeline.js +0 -69
- package/dist/tracking/token-flow.js +0 -276
- package/dist/tracking/turn-segmenter.js +0 -122
- package/dist/tracking/weekly-accumulator.js +0 -179
- package/dist/tracking/working-snapshots.js +0 -188
- package/dist/tracking/workspace-manifest.js +0 -176
- package/dist/transport/http.js +0 -102
- package/dist/utils/counterfactual.js +0 -65
- package/dist/utils/deep-link.js +0 -34
- package/dist/utils/detect.js +0 -193
- package/dist/utils/exec.js +0 -73
- package/dist/utils/file-logger.js +0 -87
- package/dist/utils/format-error.js +0 -29
- package/dist/utils/git.js +0 -181
- package/dist/utils/log.js +0 -57
- package/dist/utils/logger.js +0 -35
- package/dist/utils/mcp-content-json.js +0 -8
- package/dist/utils/session-logger.js +0 -154
- package/dist/utils/startup-log.js +0 -512
- package/dist/utils/ui.js +0 -56
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compression Quality Feedback Loop — detects when compression causes agent retries.
|
|
3
|
-
*
|
|
4
|
-
* Monitors agent behavior AFTER compression events. If retry rate spikes
|
|
5
|
-
* within 60s, automatically reduces compression aggressiveness.
|
|
6
|
-
*
|
|
7
|
-
* Adaptive logic:
|
|
8
|
-
* - Track (compression event) → (next 60s behavior)
|
|
9
|
-
* - Agent retries same entity OR re-requests same content → "over-compressed"
|
|
10
|
-
* - 3+ over-compression signals on same content type → increase retention by 20%
|
|
11
|
-
* - Hard floor: never compress below 40% retention
|
|
12
|
-
* - Reset: 10+ good compressions → cautiously reduce retention
|
|
13
|
-
*
|
|
14
|
-
* Layer 6 FE-E: per-tool Layer 6 tier (columnar → minified JSON → expanded JSON) after repeated retries.
|
|
15
|
-
*/
|
|
16
|
-
const DEFAULT_RETENTION = {
|
|
17
|
-
git_diff: 0.3,
|
|
18
|
-
test_output: 0.4,
|
|
19
|
-
directory: 0.2,
|
|
20
|
-
file_content: 0.35,
|
|
21
|
-
generic: 0.25,
|
|
22
|
-
layer6_columnar: 0.35,
|
|
23
|
-
shell_tabular: 0.32,
|
|
24
|
-
shell_structured: 0.3,
|
|
25
|
-
shell_log_text: 0.34,
|
|
26
|
-
shell_diff: 0.28,
|
|
27
|
-
shell_tree_paths: 0.32,
|
|
28
|
-
shell_key_value: 0.35,
|
|
29
|
-
shell_error_diagnostic: 0.33,
|
|
30
|
-
shell_test_results: 0.34,
|
|
31
|
-
shell_progress_streaming: 0.3,
|
|
32
|
-
shell_yaml: 0.32,
|
|
33
|
-
};
|
|
34
|
-
const HARD_FLOOR = 0.4;
|
|
35
|
-
const OVER_COMPRESSION_THRESHOLD = 3;
|
|
36
|
-
const RETENTION_INCREASE = 0.2;
|
|
37
|
-
const GOOD_STREAK_THRESHOLD = 10;
|
|
38
|
-
const RETENTION_DECREASE = 0.05;
|
|
39
|
-
const FEEDBACK_WINDOW_MS = 60_000;
|
|
40
|
-
/** FE-E.8 — downgrade Layer 6 wire format after sustained retries per tool name. */
|
|
41
|
-
const LAYER6_TIER_MINIFIED_RETRY = 3;
|
|
42
|
-
const LAYER6_TIER_EXPANDED_RETRY = 6;
|
|
43
|
-
export function createCompressionQualityMonitor() {
|
|
44
|
-
const recentCompressions = [];
|
|
45
|
-
const signals = [];
|
|
46
|
-
const overCompressionCounts = {
|
|
47
|
-
git_diff: 0,
|
|
48
|
-
test_output: 0,
|
|
49
|
-
directory: 0,
|
|
50
|
-
file_content: 0,
|
|
51
|
-
generic: 0,
|
|
52
|
-
layer6_columnar: 0,
|
|
53
|
-
shell_tabular: 0,
|
|
54
|
-
shell_structured: 0,
|
|
55
|
-
shell_log_text: 0,
|
|
56
|
-
shell_diff: 0,
|
|
57
|
-
shell_tree_paths: 0,
|
|
58
|
-
shell_key_value: 0,
|
|
59
|
-
shell_error_diagnostic: 0,
|
|
60
|
-
shell_test_results: 0,
|
|
61
|
-
shell_progress_streaming: 0,
|
|
62
|
-
shell_yaml: 0,
|
|
63
|
-
};
|
|
64
|
-
const goodStreaks = {
|
|
65
|
-
git_diff: 0,
|
|
66
|
-
test_output: 0,
|
|
67
|
-
directory: 0,
|
|
68
|
-
file_content: 0,
|
|
69
|
-
generic: 0,
|
|
70
|
-
layer6_columnar: 0,
|
|
71
|
-
shell_tabular: 0,
|
|
72
|
-
shell_structured: 0,
|
|
73
|
-
shell_log_text: 0,
|
|
74
|
-
shell_diff: 0,
|
|
75
|
-
shell_tree_paths: 0,
|
|
76
|
-
shell_key_value: 0,
|
|
77
|
-
shell_error_diagnostic: 0,
|
|
78
|
-
shell_test_results: 0,
|
|
79
|
-
shell_progress_streaming: 0,
|
|
80
|
-
shell_yaml: 0,
|
|
81
|
-
};
|
|
82
|
-
const adapted = { ...DEFAULT_RETENTION };
|
|
83
|
-
const layer6RetriesByTool = new Map();
|
|
84
|
-
function recordCompression(id, contentType, ratio) {
|
|
85
|
-
recentCompressions.push({ id, contentType, ratio, timestamp: Date.now() });
|
|
86
|
-
if (recentCompressions.length > 100)
|
|
87
|
-
recentCompressions.shift();
|
|
88
|
-
}
|
|
89
|
-
function recordAgentAction(entityKey, isRetry, isReRequest) {
|
|
90
|
-
const now = Date.now();
|
|
91
|
-
const cutoff = now - FEEDBACK_WINDOW_MS;
|
|
92
|
-
const recentForEntity = recentCompressions.filter((c) => c.timestamp > cutoff);
|
|
93
|
-
if (recentForEntity.length === 0)
|
|
94
|
-
return;
|
|
95
|
-
for (const compression of recentForEntity) {
|
|
96
|
-
const ct = compression.contentType;
|
|
97
|
-
if (isRetry || isReRequest) {
|
|
98
|
-
signals.push({
|
|
99
|
-
compressionId: compression.id,
|
|
100
|
-
contentType: ct,
|
|
101
|
-
compressionRatio: compression.ratio,
|
|
102
|
-
followedByRetry: isRetry,
|
|
103
|
-
followedByReRequest: isReRequest,
|
|
104
|
-
timestamp: now,
|
|
105
|
-
});
|
|
106
|
-
overCompressionCounts[ct] = (overCompressionCounts[ct] ?? 0) + 1;
|
|
107
|
-
goodStreaks[ct] = 0;
|
|
108
|
-
if ((overCompressionCounts[ct] ?? 0) >= OVER_COMPRESSION_THRESHOLD) {
|
|
109
|
-
adapted[ct] = Math.min(1.0, (adapted[ct] ?? DEFAULT_RETENTION[ct]) + RETENTION_INCREASE);
|
|
110
|
-
overCompressionCounts[ct] = 0;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
goodStreaks[ct] = (goodStreaks[ct] ?? 0) + 1;
|
|
115
|
-
if ((goodStreaks[ct] ?? 0) >= GOOD_STREAK_THRESHOLD) {
|
|
116
|
-
adapted[ct] = Math.max(DEFAULT_RETENTION[ct], (adapted[ct] ?? DEFAULT_RETENTION[ct]) - RETENTION_DECREASE);
|
|
117
|
-
goodStreaks[ct] = 0;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
function getRetention(contentType) {
|
|
123
|
-
return Math.max(HARD_FLOOR, adapted[contentType] ?? DEFAULT_RETENTION[contentType]);
|
|
124
|
-
}
|
|
125
|
-
function getAdaptiveConfig() {
|
|
126
|
-
const totalSignals = signals.length;
|
|
127
|
-
return {
|
|
128
|
-
minRetention: { ...DEFAULT_RETENTION },
|
|
129
|
-
adaptedRetention: { ...adapted },
|
|
130
|
-
confidence: Math.min(1.0, totalSignals * 0.05),
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
function getSignalCount() {
|
|
134
|
-
return signals.length;
|
|
135
|
-
}
|
|
136
|
-
function recordLayer6Retry(toolName) {
|
|
137
|
-
layer6RetriesByTool.set(toolName, (layer6RetriesByTool.get(toolName) ?? 0) + 1);
|
|
138
|
-
}
|
|
139
|
-
function getLayer6RetryCount(toolName) {
|
|
140
|
-
return layer6RetriesByTool.get(toolName) ?? 0;
|
|
141
|
-
}
|
|
142
|
-
function getLayer6Tier(toolName) {
|
|
143
|
-
const n = layer6RetriesByTool.get(toolName) ?? 0;
|
|
144
|
-
if (n >= LAYER6_TIER_EXPANDED_RETRY)
|
|
145
|
-
return "expanded";
|
|
146
|
-
if (n >= LAYER6_TIER_MINIFIED_RETRY)
|
|
147
|
-
return "minified";
|
|
148
|
-
return "columnar";
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
recordCompression,
|
|
152
|
-
recordAgentAction,
|
|
153
|
-
recordLayer6Retry,
|
|
154
|
-
getLayer6Tier,
|
|
155
|
-
getLayer6RetryCount,
|
|
156
|
-
getAdaptiveConfig,
|
|
157
|
-
getRetention,
|
|
158
|
-
getSignalCount,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compression Metrics Collector — tracks per-compression stats for the session.
|
|
3
|
-
*
|
|
4
|
-
* Records: content type, original size, compressed size, sections preserved/omitted,
|
|
5
|
-
* annotations added, duration. Feeds into token accounting and the quality feedback loop.
|
|
6
|
-
*/
|
|
7
|
-
let eventCounter = 0;
|
|
8
|
-
export function createCompressionStatsCollector() {
|
|
9
|
-
const events = [];
|
|
10
|
-
function record(event) {
|
|
11
|
-
const id = `comp-${++eventCounter}-${Date.now()}`;
|
|
12
|
-
events.push({ ...event, id, timestamp: Date.now() });
|
|
13
|
-
return id;
|
|
14
|
-
}
|
|
15
|
-
function getEvent(id) {
|
|
16
|
-
return events.find((e) => e.id === id) ?? null;
|
|
17
|
-
}
|
|
18
|
-
function getRecentEvents(count = 20) {
|
|
19
|
-
return events.slice(-count);
|
|
20
|
-
}
|
|
21
|
-
function getSessionStats() {
|
|
22
|
-
const stats = {
|
|
23
|
-
totalEvents: events.length,
|
|
24
|
-
totalOriginalTokens: 0,
|
|
25
|
-
totalCompressedTokens: 0,
|
|
26
|
-
totalSaved: 0,
|
|
27
|
-
avgCompressionRatio: 0,
|
|
28
|
-
byContentType: {},
|
|
29
|
-
};
|
|
30
|
-
for (const event of events) {
|
|
31
|
-
stats.totalOriginalTokens += event.originalTokens;
|
|
32
|
-
stats.totalCompressedTokens += event.compressedTokens;
|
|
33
|
-
const saved = event.originalTokens - event.compressedTokens;
|
|
34
|
-
stats.totalSaved += saved;
|
|
35
|
-
const ct = event.contentType;
|
|
36
|
-
if (!stats.byContentType[ct])
|
|
37
|
-
stats.byContentType[ct] = { count: 0, saved: 0 };
|
|
38
|
-
stats.byContentType[ct].count++;
|
|
39
|
-
stats.byContentType[ct].saved += saved;
|
|
40
|
-
}
|
|
41
|
-
stats.avgCompressionRatio =
|
|
42
|
-
stats.totalOriginalTokens > 0
|
|
43
|
-
? Math.round((stats.totalSaved / stats.totalOriginalTokens) * 100) / 100
|
|
44
|
-
: 0;
|
|
45
|
-
return stats;
|
|
46
|
-
}
|
|
47
|
-
function reset() {
|
|
48
|
-
events.length = 0;
|
|
49
|
-
}
|
|
50
|
-
return { record, getEvent, getRecentEvents, getSessionStats, reset };
|
|
51
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Context Rot Detector — detects session degradation and injects recovery.
|
|
3
|
-
*
|
|
4
|
-
* U.14: Detects when an ongoing session suffers from context rot:
|
|
5
|
-
* - Depth threshold: >200K tokens estimated → warning, >300K → critical
|
|
6
|
-
* - Repeated exploration: agent re-queries delivered entities
|
|
7
|
-
* - Declining precision: increasing error rate
|
|
8
|
-
* - Forgotten context: agent requests already-delivered info
|
|
9
|
-
* - Rule amnesia: convention violated after delivery
|
|
10
|
-
*
|
|
11
|
-
* U.15: Takes corrective action:
|
|
12
|
-
* - rot 0.4-0.7: inject context refresh
|
|
13
|
-
* - rot > 0.7: suggest new session
|
|
14
|
-
*/
|
|
15
|
-
const DEPTH_WARNING = 200_000;
|
|
16
|
-
const DEPTH_CRITICAL = 300_000;
|
|
17
|
-
const REPEATED_QUERY_THRESHOLD = 3;
|
|
18
|
-
const ERROR_SPIKE_THRESHOLD = 5;
|
|
19
|
-
export function createContextRotDetector() {
|
|
20
|
-
let estimatedDepth = 0;
|
|
21
|
-
const queryCountMap = new Map();
|
|
22
|
-
let recentErrors = 0;
|
|
23
|
-
const forgottenKeys = [];
|
|
24
|
-
const amnesiaConventions = [];
|
|
25
|
-
let lastRefreshContext = null;
|
|
26
|
-
function recordToolCallTokens(tokens) {
|
|
27
|
-
estimatedDepth += tokens;
|
|
28
|
-
}
|
|
29
|
-
function recordRepeatedQuery(entityKey) {
|
|
30
|
-
queryCountMap.set(entityKey, (queryCountMap.get(entityKey) ?? 0) + 1);
|
|
31
|
-
}
|
|
32
|
-
function recordError() {
|
|
33
|
-
recentErrors++;
|
|
34
|
-
}
|
|
35
|
-
function recordForgottenContext(key, deliveredAt) {
|
|
36
|
-
forgottenKeys.push({ key, deliveredAt, requeriedAt: Date.now() });
|
|
37
|
-
}
|
|
38
|
-
function recordConventionViolationAfterDelivery(convention) {
|
|
39
|
-
amnesiaConventions.push(convention);
|
|
40
|
-
}
|
|
41
|
-
function evaluate() {
|
|
42
|
-
const signals = [];
|
|
43
|
-
let rotScore = 0;
|
|
44
|
-
if (estimatedDepth > DEPTH_CRITICAL) {
|
|
45
|
-
signals.push({
|
|
46
|
-
type: "depth_threshold",
|
|
47
|
-
tokens: estimatedDepth,
|
|
48
|
-
threshold: DEPTH_CRITICAL,
|
|
49
|
-
});
|
|
50
|
-
rotScore += 0.4;
|
|
51
|
-
}
|
|
52
|
-
else if (estimatedDepth > DEPTH_WARNING) {
|
|
53
|
-
signals.push({
|
|
54
|
-
type: "depth_threshold",
|
|
55
|
-
tokens: estimatedDepth,
|
|
56
|
-
threshold: DEPTH_WARNING,
|
|
57
|
-
});
|
|
58
|
-
rotScore += 0.2;
|
|
59
|
-
}
|
|
60
|
-
for (const [entity, count] of queryCountMap) {
|
|
61
|
-
if (count >= REPEATED_QUERY_THRESHOLD) {
|
|
62
|
-
signals.push({
|
|
63
|
-
type: "repeated_exploration",
|
|
64
|
-
entity,
|
|
65
|
-
queryCount: count,
|
|
66
|
-
});
|
|
67
|
-
rotScore += 0.15;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (recentErrors >= ERROR_SPIKE_THRESHOLD) {
|
|
71
|
-
signals.push({ type: "declining_precision", recentErrors, window: 10 });
|
|
72
|
-
rotScore += 0.2;
|
|
73
|
-
}
|
|
74
|
-
for (const forgotten of forgottenKeys.slice(-5)) {
|
|
75
|
-
signals.push({
|
|
76
|
-
type: "forgotten_context",
|
|
77
|
-
key: forgotten.key,
|
|
78
|
-
deliveredAt: forgotten.deliveredAt,
|
|
79
|
-
requeriedAt: forgotten.requeriedAt,
|
|
80
|
-
});
|
|
81
|
-
rotScore += 0.1;
|
|
82
|
-
}
|
|
83
|
-
for (const convention of amnesiaConventions.slice(-3)) {
|
|
84
|
-
signals.push({
|
|
85
|
-
type: "rule_amnesia",
|
|
86
|
-
convention,
|
|
87
|
-
violatedAfterDelivery: true,
|
|
88
|
-
});
|
|
89
|
-
rotScore += 0.15;
|
|
90
|
-
}
|
|
91
|
-
const rotConfidence = Math.min(1.0, rotScore);
|
|
92
|
-
let action = "none";
|
|
93
|
-
if (rotConfidence > 0.7) {
|
|
94
|
-
action = "suggest_new_session";
|
|
95
|
-
}
|
|
96
|
-
else if (rotConfidence > 0.4) {
|
|
97
|
-
action = "inject_refresh";
|
|
98
|
-
}
|
|
99
|
-
if (action === "inject_refresh" || action === "suggest_new_session") {
|
|
100
|
-
lastRefreshContext = {
|
|
101
|
-
reason: action === "suggest_new_session"
|
|
102
|
-
? "severe_context_rot"
|
|
103
|
-
: "context_degradation",
|
|
104
|
-
estimated_depth: estimatedDepth,
|
|
105
|
-
rot_confidence: Math.round(rotConfidence * 100) / 100,
|
|
106
|
-
repeated_entities: [...queryCountMap.entries()]
|
|
107
|
-
.filter(([_, c]) => c >= REPEATED_QUERY_THRESHOLD)
|
|
108
|
-
.map(([e]) => e),
|
|
109
|
-
recommendation: action === "suggest_new_session"
|
|
110
|
-
? "Start a new session. Current context is degraded beyond recovery."
|
|
111
|
-
: "Critical context refreshed. Proceed with caution.",
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
return { estimatedDepth, rotConfidence, signals, action };
|
|
115
|
-
}
|
|
116
|
-
function getRefreshContext() {
|
|
117
|
-
return lastRefreshContext;
|
|
118
|
-
}
|
|
119
|
-
function reset() {
|
|
120
|
-
estimatedDepth = 0;
|
|
121
|
-
queryCountMap.clear();
|
|
122
|
-
recentErrors = 0;
|
|
123
|
-
forgottenKeys.length = 0;
|
|
124
|
-
amnesiaConventions.length = 0;
|
|
125
|
-
lastRefreshContext = null;
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
recordToolCallTokens,
|
|
129
|
-
recordRepeatedQuery,
|
|
130
|
-
recordError,
|
|
131
|
-
recordForgottenContext,
|
|
132
|
-
recordConventionViolationAfterDelivery,
|
|
133
|
-
evaluate,
|
|
134
|
-
getRefreshContext,
|
|
135
|
-
reset,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Drift-pattern detector for the Tier 1 nudge system (Nudge v2 / N2).
|
|
3
|
-
*
|
|
4
|
-
* Pure function — no I/O, no state. Given a shell command string, returns
|
|
5
|
-
* either null (no drift) or a structured suggestion describing what unerr
|
|
6
|
-
* MCP tool would have been a better choice.
|
|
7
|
-
*
|
|
8
|
-
* Patterns are kept conservative: only fire when the command CLEARLY
|
|
9
|
-
* targets code, so we don't false-positive on log greps or generic file
|
|
10
|
-
* listings.
|
|
11
|
-
*/
|
|
12
|
-
const CODE_EXTENSIONS_RE = /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|rb|java|kt|swift|cs|cpp|c|h|hpp|php|scala|ex|exs|lua|dart|zig|sh|bash|zsh)$/i;
|
|
13
|
-
// `/` is included in the prefix class so absolute paths like
|
|
14
|
-
// `/Users/foo/repo/src/proxy/` also match — agents often grep into source
|
|
15
|
-
// trees by absolute path, and those should fire the drift nudge too.
|
|
16
|
-
const CODE_PATH_HINT_RE = /(?:^|[\s'"/])(?:src|lib|app|test|tests|pkg|cmd|internal|packages|apps|components|hooks|utils|services|controllers|models)\b/;
|
|
17
|
-
/**
|
|
18
|
-
* Strip leading shell decorations (env vars, command chains) and return
|
|
19
|
-
* the first executable token plus its tail.
|
|
20
|
-
*/
|
|
21
|
-
function splitFirstCommand(cmd) {
|
|
22
|
-
// Drop leading `VAR=val VAR2=val2 ` env prefixes
|
|
23
|
-
let s = cmd.trim().replace(/^(?:[A-Z_][A-Z0-9_]*=\S+\s+)+/, "");
|
|
24
|
-
// Drop leading `time `, `sudo `, `xargs `, `env -- `
|
|
25
|
-
s = s.replace(/^(?:time|sudo|xargs|env\s+--)\s+/, "");
|
|
26
|
-
const sp = s.indexOf(" ");
|
|
27
|
-
if (sp < 0)
|
|
28
|
-
return { head: s, tail: "" };
|
|
29
|
-
return { head: s.slice(0, sp), tail: s.slice(sp + 1) };
|
|
30
|
-
}
|
|
31
|
-
/** Does the command look like it's targeting code (paths or extensions)? */
|
|
32
|
-
function looksLikeCodeTarget(tail) {
|
|
33
|
-
if (CODE_EXTENSIONS_RE.test(tail))
|
|
34
|
-
return true;
|
|
35
|
-
if (CODE_PATH_HINT_RE.test(tail))
|
|
36
|
-
return true;
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
/** Extract the search term from `grep PATTERN paths` / `rg PATTERN paths`. */
|
|
40
|
-
function extractGrepPattern(tail) {
|
|
41
|
-
// Skip leading flags like -r -n -i -E etc.
|
|
42
|
-
const parts = tail.match(/(?:"[^"]*"|'[^']*'|\S+)/g) ?? [];
|
|
43
|
-
for (const p of parts) {
|
|
44
|
-
if (p.startsWith("-"))
|
|
45
|
-
continue;
|
|
46
|
-
return p.replace(/^['"]|['"]$/g, "");
|
|
47
|
-
}
|
|
48
|
-
return undefined;
|
|
49
|
-
}
|
|
50
|
-
/** Extract the file path from `cat PATH` / `head PATH` etc. */
|
|
51
|
-
function extractReadPath(tail) {
|
|
52
|
-
const parts = tail.match(/\S+/g) ?? [];
|
|
53
|
-
for (const p of parts) {
|
|
54
|
-
if (p.startsWith("-"))
|
|
55
|
-
continue;
|
|
56
|
-
return p;
|
|
57
|
-
}
|
|
58
|
-
return undefined;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Inspect a shell command. Return a DriftHint if the command represents a
|
|
62
|
-
* code-navigation task that unerr MCP tools would do better; null otherwise.
|
|
63
|
-
*/
|
|
64
|
-
export function isDriftCommand(cmd) {
|
|
65
|
-
if (!cmd || !cmd.trim())
|
|
66
|
-
return null;
|
|
67
|
-
const { head, tail } = splitFirstCommand(cmd);
|
|
68
|
-
// --- code_search: grep/rg/egrep against code paths ---
|
|
69
|
-
// TRIM (table row #2): why-leads, drop trailing "— graph-ranked, <5ms" tail.
|
|
70
|
-
if (/^(grep|rg|egrep|fgrep)$/.test(head)) {
|
|
71
|
-
if (!looksLikeCodeTarget(tail))
|
|
72
|
-
return null;
|
|
73
|
-
const pattern = extractGrepPattern(tail);
|
|
74
|
-
return {
|
|
75
|
-
kind: "code_search",
|
|
76
|
-
suggest: pattern
|
|
77
|
-
? `search_code({query:${JSON.stringify(pattern)}}) ranks by graph, <5ms vs full-tree grep`
|
|
78
|
-
: `search_code({query:"..."}) ranks by graph, <5ms vs full-tree grep`,
|
|
79
|
-
arg: pattern,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
// --- code_search via `find -name` ---
|
|
83
|
-
if (head === "find") {
|
|
84
|
-
if (!/-i?name\b/.test(tail))
|
|
85
|
-
return null;
|
|
86
|
-
const m = tail.match(/-i?name\s+(['"]?)([^'"\s]+)\1/);
|
|
87
|
-
const name = m?.[2];
|
|
88
|
-
if (!name || !CODE_EXTENSIONS_RE.test(name))
|
|
89
|
-
return null;
|
|
90
|
-
return {
|
|
91
|
-
kind: "code_search",
|
|
92
|
-
suggest: `search_code({query:${JSON.stringify(name.replace(/^\*\.?|\.$/g, ""))}}) returns entities, not just file paths`,
|
|
93
|
-
arg: name,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
// --- code_read: cat/head/tail/less on a code file ---
|
|
97
|
-
// TRIM (table row #1): "auto-loads conventions" before the call template.
|
|
98
|
-
if (/^(cat|head|tail|less|more|bat)$/.test(head)) {
|
|
99
|
-
const path = extractReadPath(tail);
|
|
100
|
-
if (!path)
|
|
101
|
-
return null;
|
|
102
|
-
if (!CODE_EXTENSIONS_RE.test(path))
|
|
103
|
-
return null;
|
|
104
|
-
return {
|
|
105
|
-
kind: "code_read",
|
|
106
|
-
suggest: `file_read({file_path:${JSON.stringify(path)}}) auto-loads conventions; faster than cat`,
|
|
107
|
-
arg: path,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
// --- dir_explore: ls -R on a source dir ---
|
|
111
|
-
if (head === "ls") {
|
|
112
|
-
const flags = tail.match(/-\w+/g)?.join(" ") ?? "";
|
|
113
|
-
if (!/R/.test(flags))
|
|
114
|
-
return null;
|
|
115
|
-
const path = tail
|
|
116
|
-
.replace(/-\w+\s*/g, "")
|
|
117
|
-
.trim()
|
|
118
|
-
.split(/\s+/)[0];
|
|
119
|
-
if (!path)
|
|
120
|
-
return null;
|
|
121
|
-
if (!CODE_PATH_HINT_RE.test(path) && !CODE_PATH_HINT_RE.test(` ${path}`))
|
|
122
|
-
return null;
|
|
123
|
-
return {
|
|
124
|
-
kind: "dir_explore",
|
|
125
|
-
suggest: `file_outline({file_path:${JSON.stringify(path)}}) returns structure without reading bodies`,
|
|
126
|
-
arg: path,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Build a one-line nudge string for a detected drift. Format is intentionally
|
|
133
|
-
* short to keep the byte cost low — drops the internal "drift(<kind>): try"
|
|
134
|
-
* preamble (unerr taxonomy, not useful to the agent) and leads with the
|
|
135
|
-
* paste-ready call template.
|
|
136
|
-
*/
|
|
137
|
-
export function formatDriftNudge(hint) {
|
|
138
|
-
return `[unerr] ${hint.suggest}`;
|
|
139
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Efficiency Metric Tracker — session-scoped token efficiency accumulator.
|
|
3
|
-
*
|
|
4
|
-
* Layer 10 supersession: When a TokenFlowWriter is provided, the tracker
|
|
5
|
-
* derives all metrics from the unified token flow event stream instead of
|
|
6
|
-
* maintaining separate counters. This eliminates dual-counting between
|
|
7
|
-
* EfficiencyTracker and ExplorationCost.
|
|
8
|
-
*
|
|
9
|
-
* When no TokenFlowWriter is available (e.g. degraded mode), falls back
|
|
10
|
-
* to the original in-memory counter implementation.
|
|
11
|
-
*/
|
|
12
|
-
import { aggregateSession } from "../tracking/token-flow.js";
|
|
13
|
-
/**
|
|
14
|
-
* Create an efficiency tracker backed by TokenFlowWriter.
|
|
15
|
-
* The `record()` method is a no-op — all tracking is done by the token flow
|
|
16
|
-
* instrumentation points (graph_query, format_encoding, etc.).
|
|
17
|
-
* `getSnapshot()` reads from the token flow event stream.
|
|
18
|
-
*/
|
|
19
|
-
export function createEfficiencyTracker(tokenFlow) {
|
|
20
|
-
if (tokenFlow) {
|
|
21
|
-
return {
|
|
22
|
-
record: () => { },
|
|
23
|
-
getSnapshot: () => {
|
|
24
|
-
const events = tokenFlow.getSessionEvents();
|
|
25
|
-
const summary = aggregateSession(events, tokenFlow.sessionId);
|
|
26
|
-
return {
|
|
27
|
-
totalCalls: summary.total_turns,
|
|
28
|
-
originalTokens: summary.total_tokens_without,
|
|
29
|
-
deliveredTokens: summary.total_tokens_with,
|
|
30
|
-
savedTokens: summary.total_tokens_saved,
|
|
31
|
-
efficiency: summary.efficiency_pct,
|
|
32
|
-
avgSavingsPerCall: summary.total_turns > 0
|
|
33
|
-
? Math.round(summary.total_tokens_saved / summary.total_turns)
|
|
34
|
-
: 0,
|
|
35
|
-
};
|
|
36
|
-
},
|
|
37
|
-
getEfficiency: () => tokenFlow.getSessionEfficiency(),
|
|
38
|
-
getSavedTokens: () => tokenFlow.getSessionTokensSaved(),
|
|
39
|
-
reset: () => { },
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
// Fallback: standalone in-memory tracker (no TokenFlow available)
|
|
43
|
-
let totalCalls = 0;
|
|
44
|
-
let originalTokens = 0;
|
|
45
|
-
let deliveredTokens = 0;
|
|
46
|
-
return {
|
|
47
|
-
record(original, delivered) {
|
|
48
|
-
totalCalls++;
|
|
49
|
-
originalTokens += original;
|
|
50
|
-
deliveredTokens += delivered;
|
|
51
|
-
},
|
|
52
|
-
getSnapshot() {
|
|
53
|
-
const saved = Math.max(0, originalTokens - deliveredTokens);
|
|
54
|
-
return {
|
|
55
|
-
totalCalls,
|
|
56
|
-
originalTokens,
|
|
57
|
-
deliveredTokens,
|
|
58
|
-
savedTokens: saved,
|
|
59
|
-
efficiency: originalTokens === 0
|
|
60
|
-
? 0
|
|
61
|
-
: Math.round(((originalTokens - deliveredTokens) / originalTokens) * 100),
|
|
62
|
-
avgSavingsPerCall: totalCalls > 0 ? Math.round(saved / totalCalls) : 0,
|
|
63
|
-
};
|
|
64
|
-
},
|
|
65
|
-
getEfficiency() {
|
|
66
|
-
if (originalTokens === 0)
|
|
67
|
-
return 0;
|
|
68
|
-
return Math.round(((originalTokens - deliveredTokens) / originalTokens) * 100);
|
|
69
|
-
},
|
|
70
|
-
getSavedTokens() {
|
|
71
|
-
return Math.max(0, originalTokens - deliveredTokens);
|
|
72
|
-
},
|
|
73
|
-
reset() {
|
|
74
|
-
totalCalls = 0;
|
|
75
|
-
originalTokens = 0;
|
|
76
|
-
deliveredTokens = 0;
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|