@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,158 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Startup renderer — bridge between proxy boot sequence and Ink display.
|
|
3
|
-
*
|
|
4
|
-
* The proxy calls StartupRenderer methods during boot steps.
|
|
5
|
-
* The renderer drives the Ink StartupDisplay component on stderr.
|
|
6
|
-
*
|
|
7
|
-
* Handles first_boot_shown flag persistence in .unerr/state/graph_version.json.
|
|
8
|
-
*/
|
|
9
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
|
-
import { join } from "node:path";
|
|
11
|
-
import React from "react";
|
|
12
|
-
import { StartupDisplay, } from "../components/StartupDisplay.js";
|
|
13
|
-
import { ThemeProvider } from "../components/Theme.js";
|
|
14
|
-
import { renderToStderr } from "../components/render.js";
|
|
15
|
-
import { buildDeepLink } from "../utils/deep-link.js";
|
|
16
|
-
export class StartupRenderer {
|
|
17
|
-
state;
|
|
18
|
-
instance = null;
|
|
19
|
-
stepMap = new Map();
|
|
20
|
-
repoId;
|
|
21
|
-
constructor() {
|
|
22
|
-
this.state = {
|
|
23
|
-
steps: [],
|
|
24
|
-
firstBoot: false,
|
|
25
|
-
ready: false,
|
|
26
|
-
localMode: false,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
/** Start the Ink display on stderr. */
|
|
30
|
-
mount() {
|
|
31
|
-
this.instance = renderToStderr(this.renderElement());
|
|
32
|
-
}
|
|
33
|
-
/** Add a step to the sequence. Returns step index for updates. */
|
|
34
|
-
addStep(label, status = "pending", value) {
|
|
35
|
-
this.stepMap.set(label, this.state.steps.length);
|
|
36
|
-
this.state.steps.push({ label, value, status });
|
|
37
|
-
this.rerender();
|
|
38
|
-
}
|
|
39
|
-
/** Update a step's status and optional value. */
|
|
40
|
-
updateStep(label, status, value) {
|
|
41
|
-
const idx = this.stepMap.get(label);
|
|
42
|
-
if (idx === undefined)
|
|
43
|
-
return;
|
|
44
|
-
const step = this.state.steps[idx];
|
|
45
|
-
if (!step)
|
|
46
|
-
return;
|
|
47
|
-
step.status = status;
|
|
48
|
-
if (value !== undefined)
|
|
49
|
-
step.value = value;
|
|
50
|
-
this.rerender();
|
|
51
|
-
}
|
|
52
|
-
/** Set the health grade result for Act 2 display. */
|
|
53
|
-
setHealth(health, repoId) {
|
|
54
|
-
this.repoId = repoId;
|
|
55
|
-
this.state.health = health;
|
|
56
|
-
this.state.firstBoot = this.isFirstBoot();
|
|
57
|
-
// Pick most interesting entity for invitation
|
|
58
|
-
if (health.highRiskEntities.length > 0) {
|
|
59
|
-
this.state.invitationEntity = health.highRiskEntities[0]?.name;
|
|
60
|
-
}
|
|
61
|
-
// Set deep link — NEVER in Local Mode (TL-18)
|
|
62
|
-
if (repoId && !this.state.localMode) {
|
|
63
|
-
this.state.deepLink = buildDeepLink(repoId, {
|
|
64
|
-
view: "health",
|
|
65
|
-
utm_source: this.state.firstBoot ? "cli_first_boot" : "cli_startup",
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
// Mark first boot as shown
|
|
69
|
-
if (this.state.firstBoot) {
|
|
70
|
-
this.markFirstBootShown();
|
|
71
|
-
}
|
|
72
|
-
this.rerender();
|
|
73
|
-
}
|
|
74
|
-
/** Mark proxy as ready (Act 3). */
|
|
75
|
-
setReady(proxyMode) {
|
|
76
|
-
this.state.ready = true;
|
|
77
|
-
this.state.proxyMode = proxyMode;
|
|
78
|
-
// If no health data, still show deep link — NEVER in Local Mode (TL-18)
|
|
79
|
-
if (!this.state.deepLink && this.repoId && !this.state.localMode) {
|
|
80
|
-
this.state.deepLink = buildDeepLink(this.repoId, {
|
|
81
|
-
utm_source: "cli_startup",
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
this.rerender();
|
|
85
|
-
}
|
|
86
|
-
// ── Local Mode Methods ────────────────────────────────────────────
|
|
87
|
-
/** Enable Local Mode rendering. Must be called before setHealth/setReady. */
|
|
88
|
-
setLocalMode(enabled) {
|
|
89
|
-
this.state.localMode = enabled;
|
|
90
|
-
if (enabled) {
|
|
91
|
-
this.state.deepLink = undefined;
|
|
92
|
-
}
|
|
93
|
-
this.rerender();
|
|
94
|
-
}
|
|
95
|
-
/** Set Local Mode indexing statistics for Act 1. */
|
|
96
|
-
setLocalIndexStats(indexStats) {
|
|
97
|
-
this.state.localIndexStats = indexStats;
|
|
98
|
-
this.rerender();
|
|
99
|
-
}
|
|
100
|
-
/** Set BYO-LLM connection status for startup display. */
|
|
101
|
-
setByoLlmStatus(status, provider, model) {
|
|
102
|
-
this.state.byoLlmStatus = status;
|
|
103
|
-
if (provider)
|
|
104
|
-
this.state.byoLlmProvider = provider;
|
|
105
|
-
if (model)
|
|
106
|
-
this.state.byoLlmModel = model;
|
|
107
|
-
this.rerender();
|
|
108
|
-
}
|
|
109
|
-
/** Set the total tool count for Act 3. */
|
|
110
|
-
setToolCount(count) {
|
|
111
|
-
this.state.toolCount = count;
|
|
112
|
-
this.rerender();
|
|
113
|
-
}
|
|
114
|
-
/** Unmount the Ink display (after startup completes). */
|
|
115
|
-
unmount() {
|
|
116
|
-
this.instance?.unmount();
|
|
117
|
-
this.instance = null;
|
|
118
|
-
}
|
|
119
|
-
// ── First boot tracking ──────────────────────────────────────────
|
|
120
|
-
isFirstBoot() {
|
|
121
|
-
const versionPath = join(process.cwd(), ".unerr", "state", "graph_version.json");
|
|
122
|
-
if (!existsSync(versionPath))
|
|
123
|
-
return true;
|
|
124
|
-
try {
|
|
125
|
-
const data = JSON.parse(readFileSync(versionPath, "utf-8"));
|
|
126
|
-
return !data.first_boot_shown;
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
markFirstBootShown() {
|
|
133
|
-
const stateDir = join(process.cwd(), ".unerr", "state");
|
|
134
|
-
const versionPath = join(stateDir, "graph_version.json");
|
|
135
|
-
try {
|
|
136
|
-
let data = {};
|
|
137
|
-
if (existsSync(versionPath)) {
|
|
138
|
-
data = JSON.parse(readFileSync(versionPath, "utf-8"));
|
|
139
|
-
}
|
|
140
|
-
data.first_boot_shown = true;
|
|
141
|
-
writeFileSync(versionPath, JSON.stringify(data, null, 2));
|
|
142
|
-
}
|
|
143
|
-
catch {
|
|
144
|
-
// Non-critical
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
// ── Ink rendering ────────────────────────────────────────────────
|
|
148
|
-
renderElement() {
|
|
149
|
-
return React.createElement(ThemeProvider, null, React.createElement(StartupDisplay, {
|
|
150
|
-
state: this.state,
|
|
151
|
-
}));
|
|
152
|
-
}
|
|
153
|
-
rerender() {
|
|
154
|
-
if (this.instance) {
|
|
155
|
-
this.instance.rerender(this.renderElement());
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Task Token Display — formats tokens-per-task for session summary.
|
|
3
|
-
*
|
|
4
|
-
* T.12: Consumes intent-level grouping data and produces formatted display.
|
|
5
|
-
* Shows top 3 most expensive tasks with entity lists and efficiency.
|
|
6
|
-
*/
|
|
7
|
-
import { calculateDollarSavings, formatDollars } from "./model-pricing.js";
|
|
8
|
-
/**
|
|
9
|
-
* Build task cost summaries from intent group data.
|
|
10
|
-
*/
|
|
11
|
-
export function buildTaskCostSummaries(intentGroups, modelId) {
|
|
12
|
-
const tasks = intentGroups
|
|
13
|
-
.filter((g) => g.toolCalls > 0)
|
|
14
|
-
.map((g) => {
|
|
15
|
-
const total = g.tokensConsumed + g.tokensSaved;
|
|
16
|
-
const efficiency = total > 0 ? Math.round((g.tokensSaved / total) * 100) : 0;
|
|
17
|
-
return {
|
|
18
|
-
taskDescription: g.prompt ?? `Task ${g.intentId}`,
|
|
19
|
-
toolCalls: g.toolCalls,
|
|
20
|
-
tokensConsumed: g.tokensConsumed,
|
|
21
|
-
tokensSaved: g.tokensSaved,
|
|
22
|
-
dollarCost: calculateDollarSavings(g.tokensConsumed, modelId),
|
|
23
|
-
efficiency,
|
|
24
|
-
entities: g.entitiesModified,
|
|
25
|
-
};
|
|
26
|
-
})
|
|
27
|
-
.sort((a, b) => b.tokensConsumed - a.tokensConsumed);
|
|
28
|
-
const top3 = tasks.slice(0, 3);
|
|
29
|
-
const totalCalls = tasks.reduce((s, t) => s + t.toolCalls, 0);
|
|
30
|
-
const totalSaved = tasks.reduce((s, t) => s + t.tokensSaved, 0);
|
|
31
|
-
const totalWithout = tasks.reduce((s, t) => s + t.tokensConsumed + t.tokensSaved, 0);
|
|
32
|
-
const formattedLines = [
|
|
33
|
-
"Tasks this session:",
|
|
34
|
-
...top3.map((t, i) => ` ${i + 1}. "${t.taskDescription.slice(0, 50)}" — ${t.toolCalls} calls, ${formatDollars(t.dollarCost)} (${t.efficiency}% optimized)`),
|
|
35
|
-
` Total: ${totalCalls} calls, ${formatDollars(calculateDollarSavings(totalSaved, modelId))} saved (${formatDollars(calculateDollarSavings(totalWithout, modelId))} without unerr)`,
|
|
36
|
-
];
|
|
37
|
-
return { tasks, totalCalls, totalSaved, totalWithout, formattedLines };
|
|
38
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Live Token Counter — accumulates tokens_saved across the session.
|
|
3
|
-
*
|
|
4
|
-
* Emits to stderr every N tool calls with a formatted summary.
|
|
5
|
-
* Uses character/4 estimation (Sprint G upgrades to tiktoken).
|
|
6
|
-
*
|
|
7
|
-
* Design: pure accumulator with configurable emit interval and sink.
|
|
8
|
-
* The sink defaults to process.stderr but can be injected for testing.
|
|
9
|
-
*/
|
|
10
|
-
function formatTokens(n) {
|
|
11
|
-
if (n >= 1_000_000)
|
|
12
|
-
return `${(n / 1_000_000).toFixed(1)}M`;
|
|
13
|
-
if (n >= 1_000)
|
|
14
|
-
return `${(n / 1_000).toFixed(1)}K`;
|
|
15
|
-
return String(n);
|
|
16
|
-
}
|
|
17
|
-
export function createTokenCounter(options = {}) {
|
|
18
|
-
const emitEveryN = options.emitEveryN ?? 10;
|
|
19
|
-
const sink = options.sink ?? ((msg) => process.stderr.write(msg));
|
|
20
|
-
let totalSaved = 0;
|
|
21
|
-
let totalProcessed = 0;
|
|
22
|
-
let callCount = 0;
|
|
23
|
-
function record(tokensSaved, totalTokens) {
|
|
24
|
-
totalSaved += tokensSaved;
|
|
25
|
-
totalProcessed += totalTokens;
|
|
26
|
-
callCount++;
|
|
27
|
-
if (callCount > 0 && callCount % emitEveryN === 0) {
|
|
28
|
-
const efficiency = totalProcessed > 0
|
|
29
|
-
? Math.round((totalSaved / totalProcessed) * 100)
|
|
30
|
-
: 0;
|
|
31
|
-
sink(`[unerr] ${formatTokens(totalSaved)} tokens saved (efficiency: ${efficiency}%)\n`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function getTotalSaved() {
|
|
35
|
-
return totalSaved;
|
|
36
|
-
}
|
|
37
|
-
function getTotalProcessed() {
|
|
38
|
-
return totalProcessed;
|
|
39
|
-
}
|
|
40
|
-
function getCallCount() {
|
|
41
|
-
return callCount;
|
|
42
|
-
}
|
|
43
|
-
function getEfficiency() {
|
|
44
|
-
return totalProcessed > 0
|
|
45
|
-
? Math.round((totalSaved / totalProcessed) * 100)
|
|
46
|
-
: 0;
|
|
47
|
-
}
|
|
48
|
-
function reset() {
|
|
49
|
-
totalSaved = 0;
|
|
50
|
-
totalProcessed = 0;
|
|
51
|
-
callCount = 0;
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
record,
|
|
55
|
-
getTotalSaved,
|
|
56
|
-
getTotalProcessed,
|
|
57
|
-
getCallCount,
|
|
58
|
-
getEfficiency,
|
|
59
|
-
reset,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Semantic Tool Clusters — groups tools by task domain.
|
|
3
|
-
*
|
|
4
|
-
* When agents call tools/list, we return ALL tools (MCP spec requires it)
|
|
5
|
-
* but REORDER them so the most relevant cluster appears first. Agents
|
|
6
|
-
* tend to use tools listed earlier — reordering is a soft adoption boost.
|
|
7
|
-
*
|
|
8
|
-
* Based on RAG-MCP research: presenting relevant subset first → 3x accuracy.
|
|
9
|
-
* We can't filter (agents may need any tool) but we CAN prioritize.
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* Semantic tool clusters — ordered from most to least commonly needed.
|
|
13
|
-
* Default ordering (no context): navigation first, then file-access, quality, persistence, shell.
|
|
14
|
-
*/
|
|
15
|
-
export const TOOL_CLUSTERS = [
|
|
16
|
-
{
|
|
17
|
-
id: "navigation",
|
|
18
|
-
name: "Code Navigation",
|
|
19
|
-
tools: [
|
|
20
|
-
"search_code",
|
|
21
|
-
"get_entity",
|
|
22
|
-
"get_references",
|
|
23
|
-
"get_file",
|
|
24
|
-
"get_imports",
|
|
25
|
-
],
|
|
26
|
-
triggerKeywords: [
|
|
27
|
-
"find",
|
|
28
|
-
"search",
|
|
29
|
-
"where",
|
|
30
|
-
"who calls",
|
|
31
|
-
"callers",
|
|
32
|
-
"callees",
|
|
33
|
-
"references",
|
|
34
|
-
"imports",
|
|
35
|
-
"depends",
|
|
36
|
-
"usage",
|
|
37
|
-
],
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
id: "file-access",
|
|
41
|
-
name: "File Access",
|
|
42
|
-
tools: ["file_outline", "file_read"],
|
|
43
|
-
triggerKeywords: [
|
|
44
|
-
"read",
|
|
45
|
-
"file",
|
|
46
|
-
"outline",
|
|
47
|
-
"structure",
|
|
48
|
-
"show me",
|
|
49
|
-
"open",
|
|
50
|
-
"look at",
|
|
51
|
-
],
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
id: "quality",
|
|
55
|
-
name: "Quality & Conventions",
|
|
56
|
-
tools: ["get_conventions"],
|
|
57
|
-
triggerKeywords: [
|
|
58
|
-
"rules",
|
|
59
|
-
"conventions",
|
|
60
|
-
"lint",
|
|
61
|
-
"style",
|
|
62
|
-
"validate",
|
|
63
|
-
"check",
|
|
64
|
-
"standard",
|
|
65
|
-
"pattern",
|
|
66
|
-
],
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
id: "structural",
|
|
70
|
-
name: "Structural Analysis",
|
|
71
|
-
tools: [
|
|
72
|
-
"get_critical_nodes",
|
|
73
|
-
"get_cross_boundary_links",
|
|
74
|
-
"file_connections",
|
|
75
|
-
"get_test_coverage",
|
|
76
|
-
"get_project_stats",
|
|
77
|
-
],
|
|
78
|
-
triggerKeywords: [
|
|
79
|
-
"chokepoint",
|
|
80
|
-
"critical",
|
|
81
|
-
"coupling",
|
|
82
|
-
"boundary",
|
|
83
|
-
"connections",
|
|
84
|
-
"test coverage",
|
|
85
|
-
"stats",
|
|
86
|
-
"overview",
|
|
87
|
-
"risk",
|
|
88
|
-
"fan_in",
|
|
89
|
-
"blast radius",
|
|
90
|
-
"dependencies",
|
|
91
|
-
],
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
id: "persistence",
|
|
95
|
-
name: "Persistent Intelligence",
|
|
96
|
-
tools: ["record_fact", "recall_facts"],
|
|
97
|
-
triggerKeywords: [
|
|
98
|
-
"remember",
|
|
99
|
-
"fact",
|
|
100
|
-
"convention",
|
|
101
|
-
"anti-pattern",
|
|
102
|
-
"record",
|
|
103
|
-
"recall",
|
|
104
|
-
],
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
id: "session-narrative",
|
|
108
|
-
name: "Session Narrative",
|
|
109
|
-
tools: ["mark_intent", "mark_decision", "mark_blocker", "mark_resolution"],
|
|
110
|
-
triggerKeywords: [
|
|
111
|
-
"intent",
|
|
112
|
-
"decision",
|
|
113
|
-
"blocker",
|
|
114
|
-
"stuck",
|
|
115
|
-
"resolved",
|
|
116
|
-
"fixed",
|
|
117
|
-
"starting",
|
|
118
|
-
"planning",
|
|
119
|
-
],
|
|
120
|
-
},
|
|
121
|
-
];
|
|
122
|
-
/**
|
|
123
|
-
* Map from tool name → cluster id for fast lookup.
|
|
124
|
-
*/
|
|
125
|
-
const TOOL_TO_CLUSTER = new Map();
|
|
126
|
-
for (const cluster of TOOL_CLUSTERS) {
|
|
127
|
-
for (const tool of cluster.tools) {
|
|
128
|
-
TOOL_TO_CLUSTER.set(tool, cluster.id);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Get the cluster ID for a tool name.
|
|
133
|
-
*/
|
|
134
|
-
export function getToolCluster(toolName) {
|
|
135
|
-
return TOOL_TO_CLUSTER.get(toolName);
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Recent tool usage tracker — determines which clusters are "hot".
|
|
139
|
-
*
|
|
140
|
-
* Tracks last N tool calls with timestamps. Clusters with recent calls
|
|
141
|
-
* get a priority boost in tools/list ordering.
|
|
142
|
-
*/
|
|
143
|
-
export class ToolUsageTracker {
|
|
144
|
-
/** Ring buffer of recent tool calls: [toolName, timestamp]. */
|
|
145
|
-
history = [];
|
|
146
|
-
maxHistory;
|
|
147
|
-
constructor(maxHistory = 50) {
|
|
148
|
-
this.maxHistory = maxHistory;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Record a tool call.
|
|
152
|
-
*/
|
|
153
|
-
record(toolName) {
|
|
154
|
-
this.history.push({ tool: toolName, ts: Date.now() });
|
|
155
|
-
if (this.history.length > this.maxHistory) {
|
|
156
|
-
this.history.shift();
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Get cluster priority scores based on recent usage.
|
|
161
|
-
* Higher score = more recently/frequently used cluster.
|
|
162
|
-
*
|
|
163
|
-
* Scoring: each tool call contributes 1/(age_in_calls + 1) to its cluster.
|
|
164
|
-
* Recent calls score higher than older ones.
|
|
165
|
-
*/
|
|
166
|
-
getClusterScores() {
|
|
167
|
-
const scores = new Map();
|
|
168
|
-
const len = this.history.length;
|
|
169
|
-
for (let i = 0; i < len; i++) {
|
|
170
|
-
const entry = this.history[i];
|
|
171
|
-
const clusterId = TOOL_TO_CLUSTER.get(entry.tool);
|
|
172
|
-
if (!clusterId)
|
|
173
|
-
continue;
|
|
174
|
-
// Recency weight: more recent = higher weight
|
|
175
|
-
const recencyWeight = 1 / (len - i);
|
|
176
|
-
scores.set(clusterId, (scores.get(clusterId) ?? 0) + recencyWeight);
|
|
177
|
-
}
|
|
178
|
-
return scores;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Get the number of recorded tool calls.
|
|
182
|
-
*/
|
|
183
|
-
getCallCount() {
|
|
184
|
-
return this.history.length;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Get the most recently used cluster ID, or null if no history.
|
|
188
|
-
*/
|
|
189
|
-
getMostRecentCluster() {
|
|
190
|
-
if (this.history.length === 0)
|
|
191
|
-
return null;
|
|
192
|
-
const lastEntry = this.history[this.history.length - 1];
|
|
193
|
-
if (!lastEntry)
|
|
194
|
-
return null;
|
|
195
|
-
const lastTool = lastEntry.tool;
|
|
196
|
-
return TOOL_TO_CLUSTER.get(lastTool) ?? null;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Reorder tool definitions by cluster priority.
|
|
201
|
-
*
|
|
202
|
-
* All tools are always returned (MCP spec compliance). The order changes
|
|
203
|
-
* based on which clusters scored highest from recent usage.
|
|
204
|
-
*
|
|
205
|
-
* @param tools - Original tool definitions array
|
|
206
|
-
* @param tracker - Usage tracker (null = use default order)
|
|
207
|
-
* @returns Reordered tool definitions (same tools, different order)
|
|
208
|
-
*/
|
|
209
|
-
export function reorderToolsByCluster(tools, tracker) {
|
|
210
|
-
if (!tracker || tracker.getCallCount() === 0) {
|
|
211
|
-
// No usage data — use default cluster order
|
|
212
|
-
return reorderByDefaultClusters(tools);
|
|
213
|
-
}
|
|
214
|
-
const scores = tracker.getClusterScores();
|
|
215
|
-
// Sort clusters by score (descending), keeping default order for unscored
|
|
216
|
-
const sortedClusterIds = TOOL_CLUSTERS.map((c) => c.id).sort((a, b) => {
|
|
217
|
-
const scoreA = scores.get(a) ?? 0;
|
|
218
|
-
const scoreB = scores.get(b) ?? 0;
|
|
219
|
-
if (scoreA !== scoreB)
|
|
220
|
-
return scoreB - scoreA;
|
|
221
|
-
// Stable: preserve default order for ties
|
|
222
|
-
return (TOOL_CLUSTERS.findIndex((c) => c.id === a) -
|
|
223
|
-
TOOL_CLUSTERS.findIndex((c) => c.id === b));
|
|
224
|
-
});
|
|
225
|
-
// Build ordered tool list: clustered tools first (in priority order), unclustered tools last
|
|
226
|
-
const toolMap = new Map(tools.map((t) => [t.name, t]));
|
|
227
|
-
const result = [];
|
|
228
|
-
const added = new Set();
|
|
229
|
-
for (const clusterId of sortedClusterIds) {
|
|
230
|
-
const cluster = TOOL_CLUSTERS.find((c) => c.id === clusterId);
|
|
231
|
-
if (!cluster)
|
|
232
|
-
continue;
|
|
233
|
-
for (const toolName of cluster.tools) {
|
|
234
|
-
const tool = toolMap.get(toolName);
|
|
235
|
-
if (tool && !added.has(toolName)) {
|
|
236
|
-
result.push(tool);
|
|
237
|
-
added.add(toolName);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// Append any tools not in any cluster (future-proofing)
|
|
242
|
-
for (const tool of tools) {
|
|
243
|
-
if (!added.has(tool.name)) {
|
|
244
|
-
result.push(tool);
|
|
245
|
-
added.add(tool.name);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return result;
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Reorder tools by default cluster ordering (no usage data).
|
|
252
|
-
*/
|
|
253
|
-
function reorderByDefaultClusters(tools) {
|
|
254
|
-
const toolMap = new Map(tools.map((t) => [t.name, t]));
|
|
255
|
-
const result = [];
|
|
256
|
-
const added = new Set();
|
|
257
|
-
for (const cluster of TOOL_CLUSTERS) {
|
|
258
|
-
for (const toolName of cluster.tools) {
|
|
259
|
-
const tool = toolMap.get(toolName);
|
|
260
|
-
if (tool && !added.has(toolName)) {
|
|
261
|
-
result.push(tool);
|
|
262
|
-
added.add(toolName);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
for (const tool of tools) {
|
|
267
|
-
if (!added.has(tool.name)) {
|
|
268
|
-
result.push(tool);
|
|
269
|
-
added.add(tool.name);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return result;
|
|
273
|
-
}
|