@unerr-ai/unerr 0.2.1 → 0.2.3
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 +36 -45
- package/dist/cli.js +37443 -36022
- package/package.json +2 -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,139 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
// ── Local Timeline from Shadow Ledger ─────────────────────────
|
|
4
|
-
/**
|
|
5
|
-
* Format a relative time string from an ISO timestamp.
|
|
6
|
-
*/
|
|
7
|
-
export function formatRelativeTime(isoTs) {
|
|
8
|
-
const diff = Date.now() - new Date(isoTs).getTime();
|
|
9
|
-
const seconds = Math.floor(diff / 1000);
|
|
10
|
-
if (seconds < 60)
|
|
11
|
-
return `${seconds}s ago`;
|
|
12
|
-
const minutes = Math.floor(seconds / 60);
|
|
13
|
-
if (minutes < 60)
|
|
14
|
-
return `${minutes} min ago`;
|
|
15
|
-
const hours = Math.floor(minutes / 60);
|
|
16
|
-
if (hours < 24)
|
|
17
|
-
return `${hours}h ago`;
|
|
18
|
-
const days = Math.floor(hours / 24);
|
|
19
|
-
return `${days}d ago`;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Read and parse shadow ledger JSONL file.
|
|
23
|
-
*/
|
|
24
|
-
export function readShadowLedger(ledgerPath) {
|
|
25
|
-
if (!fs.existsSync(ledgerPath))
|
|
26
|
-
return [];
|
|
27
|
-
try {
|
|
28
|
-
const raw = fs.readFileSync(ledgerPath, "utf-8");
|
|
29
|
-
const entries = [];
|
|
30
|
-
for (const line of raw.split("\n")) {
|
|
31
|
-
const trimmed = line.trim();
|
|
32
|
-
if (!trimmed)
|
|
33
|
-
continue;
|
|
34
|
-
try {
|
|
35
|
-
entries.push(JSON.parse(trimmed));
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
// Skip malformed lines
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return entries;
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return [];
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Load working state snapshot SHAs for star markers.
|
|
49
|
-
*/
|
|
50
|
-
function loadWorkingSnapshots(unerrDir) {
|
|
51
|
-
const shas = new Set();
|
|
52
|
-
const stateDir = path.join(unerrDir, "state");
|
|
53
|
-
if (!fs.existsSync(stateDir))
|
|
54
|
-
return shas;
|
|
55
|
-
try {
|
|
56
|
-
const entries = fs.readdirSync(stateDir, { withFileTypes: true });
|
|
57
|
-
for (const entry of entries) {
|
|
58
|
-
if (entry.name.startsWith("working-") && entry.name.endsWith(".json")) {
|
|
59
|
-
try {
|
|
60
|
-
const raw = fs.readFileSync(path.join(stateDir, entry.name), "utf-8");
|
|
61
|
-
const snapshot = JSON.parse(raw);
|
|
62
|
-
if (snapshot.commitSha)
|
|
63
|
-
shas.add(snapshot.commitSha);
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
// Skip corrupt files
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
// Non-blocking
|
|
73
|
-
}
|
|
74
|
-
return shas;
|
|
75
|
-
}
|
|
76
|
-
export function runTimelineLocal(opts) {
|
|
77
|
-
const cwd = process.cwd();
|
|
78
|
-
const unerrDir = path.join(cwd, ".unerr");
|
|
79
|
-
const ledgerPath = path.join(unerrDir, "ledger", "shadow.jsonl");
|
|
80
|
-
let entries = readShadowLedger(ledgerPath);
|
|
81
|
-
if (entries.length === 0) {
|
|
82
|
-
process.stderr.write("[unerr] No ledger entries found.\n");
|
|
83
|
-
process.stderr.write("[unerr] The shadow ledger is populated as you use unerr tools.\n");
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
// Apply filters
|
|
87
|
-
if (opts.branch) {
|
|
88
|
-
entries = entries.filter((e) => e.branch === opts.branch);
|
|
89
|
-
}
|
|
90
|
-
if (opts.tool) {
|
|
91
|
-
entries = entries.filter((e) => e.tool === opts.tool);
|
|
92
|
-
}
|
|
93
|
-
// Take last N entries (most recent)
|
|
94
|
-
const total = entries.length;
|
|
95
|
-
entries = entries.slice(-opts.limit);
|
|
96
|
-
// Load working state markers
|
|
97
|
-
const workingShas = loadWorkingSnapshots(unerrDir);
|
|
98
|
-
process.stderr.write("\n");
|
|
99
|
-
for (const entry of entries) {
|
|
100
|
-
const timestamp = formatRelativeTime(entry.ts).padEnd(12);
|
|
101
|
-
const toolName = entry.tool.padEnd(22);
|
|
102
|
-
const branch = `[${entry.branch}]`;
|
|
103
|
-
const isWorking = workingShas.has(entry.head_sha);
|
|
104
|
-
const marker = isWorking ? " *" : "";
|
|
105
|
-
process.stderr.write(` ${timestamp}${toolName} ${branch}${marker}\n`);
|
|
106
|
-
// Show args summary if available
|
|
107
|
-
if (entry.args_summary && Object.keys(entry.args_summary).length > 0) {
|
|
108
|
-
const summary = Object.entries(entry.args_summary)
|
|
109
|
-
.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`)
|
|
110
|
-
.join(", ")
|
|
111
|
-
.slice(0, 80);
|
|
112
|
-
process.stderr.write(` ${summary}\n`);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
const workingCount = entries.filter((e) => workingShas.has(e.head_sha)).length;
|
|
116
|
-
process.stderr.write(`\n ${entries.length} entries shown${total > entries.length ? ` (of ${total} total)` : ""} · ${workingCount} working states marked\n\n`);
|
|
117
|
-
}
|
|
118
|
-
export function registerTimelineCommand(program) {
|
|
119
|
-
program
|
|
120
|
-
.command("timeline")
|
|
121
|
-
.description("Show the prompt ledger timeline")
|
|
122
|
-
.option("--branch <branch>", "Filter by branch")
|
|
123
|
-
.option("--tool <tool>", "Filter by tool name")
|
|
124
|
-
.option("--limit <n>", "Number of entries to show", "50")
|
|
125
|
-
.action(async (opts) => {
|
|
126
|
-
try {
|
|
127
|
-
runTimelineLocal({
|
|
128
|
-
branch: opts.branch,
|
|
129
|
-
tool: opts.tool,
|
|
130
|
-
limit: Number.parseInt(opts.limit, 10) || 50,
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
catch (error) {
|
|
134
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
135
|
-
console.error(`Error: ${message}`);
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
}
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `unerr uninstall [agent]` — removes generated configs, skills, hooks, and instructions.
|
|
3
|
-
*
|
|
4
|
-
* Two modes:
|
|
5
|
-
* - `unerr uninstall claude` — per-agent: reverts exactly what `unerr install claude` did
|
|
6
|
-
* - `unerr uninstall` (no args) — removes all agents' configs
|
|
7
|
-
*
|
|
8
|
-
* Does NOT remove:
|
|
9
|
-
* - .unerr/ data directory (user's indexed data)
|
|
10
|
-
* - .gitignore entries (shared across agents)
|
|
11
|
-
*/
|
|
12
|
-
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
13
|
-
import { join } from "node:path";
|
|
14
|
-
import { AGENT_REGISTRY, getAgent, normalizeAgentName, } from "../config/agent-registry.js";
|
|
15
|
-
import { removeDisallowedTools, removePreToolUseBashHook, } from "../config/claude-settings-hooks.js";
|
|
16
|
-
import { removeClaudeHook } from "../config/hook-installer.js";
|
|
17
|
-
import { removeInstructionSection } from "../config/instruction-writer.js";
|
|
18
|
-
import { removeMcpConfig } from "../config/mcp-config-writer.js";
|
|
19
|
-
import { removeInstalledSkills } from "../skills/resolver.js";
|
|
20
|
-
export function registerUninstallCommand(program) {
|
|
21
|
-
program
|
|
22
|
-
.command("uninstall [agent]")
|
|
23
|
-
.description("Remove unerr configs and hooks from this project")
|
|
24
|
-
.option("--autostart", "Remove the platform auto-start service (launchd/systemd/schtasks)")
|
|
25
|
-
.action(async (agent, opts) => {
|
|
26
|
-
const cwd = process.cwd();
|
|
27
|
-
if (opts.autostart) {
|
|
28
|
-
try {
|
|
29
|
-
const { uninstallForCurrentPlatform, removeSentinel } = await import("../daemon/autostart.js");
|
|
30
|
-
const result = await uninstallForCurrentPlatform();
|
|
31
|
-
removeSentinel();
|
|
32
|
-
process.stderr.write(`\x1b[38;2;52;211;153m✓\x1b[0m Platform auto-start removed${result.error ? ` (note: ${result.error})` : ""}\n`);
|
|
33
|
-
}
|
|
34
|
-
catch (err) {
|
|
35
|
-
process.stderr.write(`\x1b[38;2;248;113;113m✗\x1b[0m Failed to remove auto-start: ${err.message}\n`);
|
|
36
|
-
}
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (agent) {
|
|
40
|
-
const normalized = normalizeAgentName(agent);
|
|
41
|
-
const agentDef = getAgent(normalized);
|
|
42
|
-
if (!agentDef) {
|
|
43
|
-
process.stderr.write(`\x1b[31m✗\x1b[0m Unknown agent: "${agent}"\n`);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const result = runUninstall(cwd, normalized);
|
|
47
|
-
displayUninstallResult(agentDef.name, result);
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
runUninstallAll(cwd);
|
|
51
|
-
}
|
|
52
|
-
// Hint about autostart removal
|
|
53
|
-
try {
|
|
54
|
-
const { isAutostartInstalled } = await import("../daemon/autostart.js");
|
|
55
|
-
if (isAutostartInstalled()) {
|
|
56
|
-
process.stderr.write("\n \x1b[38;2;251;191;36m⚠\x1b[0m Platform auto-start is still active. Remove with: unerr uninstall --autostart\n\n");
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
// Non-blocking
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Uninstall unerr for a single agent — symmetric to runInstall().
|
|
66
|
-
*/
|
|
67
|
-
function runUninstall(cwd, ide) {
|
|
68
|
-
// 1. Remove MCP config
|
|
69
|
-
const mcpRemoved = removeMcpConfig(cwd, ide);
|
|
70
|
-
// 2. Remove skills
|
|
71
|
-
let skillsRemoved = 0;
|
|
72
|
-
try {
|
|
73
|
-
skillsRemoved = removeInstalledSkills(ide, cwd);
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
// Non-blocking
|
|
77
|
-
}
|
|
78
|
-
// 3. Remove hooks (agent-specific)
|
|
79
|
-
let hookRemoved = false;
|
|
80
|
-
let settingsHookRemoved = false;
|
|
81
|
-
if (ide === "claude-code") {
|
|
82
|
-
hookRemoved = removeClaudeHook(cwd);
|
|
83
|
-
settingsHookRemoved = removePreToolUseBashHook(cwd);
|
|
84
|
-
}
|
|
85
|
-
else if (ide === "cursor") {
|
|
86
|
-
hookRemoved = removeCursorHooks(cwd);
|
|
87
|
-
}
|
|
88
|
-
else if (ide === "cline") {
|
|
89
|
-
hookRemoved = removeClineHooks(cwd);
|
|
90
|
-
}
|
|
91
|
-
// 4. Gitignore — NOT reverted (shared across agents, .unerr/ data preserved)
|
|
92
|
-
// 5. Remove instructions
|
|
93
|
-
let instructionsRemoved = false;
|
|
94
|
-
try {
|
|
95
|
-
instructionsRemoved = removeInstructionSection(cwd, ide);
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
// Non-blocking
|
|
99
|
-
}
|
|
100
|
-
// 6. S8: Remove disallowed tool entries (Claude Code only)
|
|
101
|
-
let disallowedToolsRemoved = false;
|
|
102
|
-
if (ide === "claude-code") {
|
|
103
|
-
try {
|
|
104
|
-
disallowedToolsRemoved = removeDisallowedTools(cwd);
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
// Non-blocking
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return {
|
|
111
|
-
mcpRemoved,
|
|
112
|
-
skillsRemoved,
|
|
113
|
-
hookRemoved,
|
|
114
|
-
settingsHookRemoved,
|
|
115
|
-
instructionsRemoved,
|
|
116
|
-
disallowedToolsRemoved,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Display per-agent uninstall results (matches install's ANSI style).
|
|
121
|
-
*/
|
|
122
|
-
function displayUninstallResult(agentName, result) {
|
|
123
|
-
process.stderr.write("\n");
|
|
124
|
-
process.stderr.write(` \x1b[38;2;139;92;246m◆\x1b[0m \x1b[1munerr ✗ ${agentName}\x1b[0m\n`);
|
|
125
|
-
process.stderr.write("\n");
|
|
126
|
-
const nothingRemoved = !result.mcpRemoved &&
|
|
127
|
-
result.skillsRemoved === 0 &&
|
|
128
|
-
!result.hookRemoved &&
|
|
129
|
-
!result.settingsHookRemoved &&
|
|
130
|
-
!result.instructionsRemoved &&
|
|
131
|
-
!result.disallowedToolsRemoved;
|
|
132
|
-
if (nothingRemoved) {
|
|
133
|
-
process.stderr.write(" \x1b[38;2;161;161;170m· Nothing to uninstall\x1b[0m\n");
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
if (result.mcpRemoved) {
|
|
137
|
-
process.stderr.write(" \x1b[38;2;52;211;153m✓\x1b[0m MCP config removed\n");
|
|
138
|
-
}
|
|
139
|
-
if (result.skillsRemoved > 0) {
|
|
140
|
-
process.stderr.write(` \x1b[38;2;52;211;153m✓\x1b[0m ${result.skillsRemoved} skills removed\n`);
|
|
141
|
-
}
|
|
142
|
-
if (result.hookRemoved) {
|
|
143
|
-
process.stderr.write(" \x1b[38;2;52;211;153m✓\x1b[0m PostToolUse hook removed\n");
|
|
144
|
-
}
|
|
145
|
-
if (result.settingsHookRemoved) {
|
|
146
|
-
process.stderr.write(" \x1b[38;2;52;211;153m✓\x1b[0m PreToolUse settings hook removed\n");
|
|
147
|
-
}
|
|
148
|
-
if (result.instructionsRemoved) {
|
|
149
|
-
process.stderr.write(" \x1b[38;2;52;211;153m✓\x1b[0m Tool preferences removed\n");
|
|
150
|
-
}
|
|
151
|
-
if (result.disallowedToolsRemoved) {
|
|
152
|
-
process.stderr.write(" \x1b[38;2;52;211;153m✓\x1b[0m Disallowed tools restored\n");
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
process.stderr.write("\n");
|
|
156
|
-
process.stderr.write(" \x1b[38;2;161;161;170mData in .unerr/ preserved.\x1b[0m\n");
|
|
157
|
-
process.stderr.write("\n");
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Uninstall all agents — enhanced version of original behavior.
|
|
161
|
-
*/
|
|
162
|
-
function runUninstallAll(cwd) {
|
|
163
|
-
const results = [];
|
|
164
|
-
for (const agent of AGENT_REGISTRY) {
|
|
165
|
-
const r = runUninstall(cwd, agent.id);
|
|
166
|
-
if (r.mcpRemoved)
|
|
167
|
-
results.push(`Removed MCP config for ${agent.id}`);
|
|
168
|
-
if (r.skillsRemoved > 0)
|
|
169
|
-
results.push(`Removed ${r.skillsRemoved} skills for ${agent.id}`);
|
|
170
|
-
if (r.hookRemoved)
|
|
171
|
-
results.push("Removed PostToolUse hook");
|
|
172
|
-
if (r.settingsHookRemoved)
|
|
173
|
-
results.push("Removed PreToolUse settings hook");
|
|
174
|
-
if (r.instructionsRemoved)
|
|
175
|
-
results.push(`Removed instructions for ${agent.id}`);
|
|
176
|
-
if (r.disallowedToolsRemoved)
|
|
177
|
-
results.push("Restored disallowed built-in tools");
|
|
178
|
-
}
|
|
179
|
-
if (results.length === 0) {
|
|
180
|
-
process.stderr.write("[unerr] Nothing to uninstall — no configs found.\n");
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
for (const r of results) {
|
|
184
|
-
process.stderr.write(`[unerr] ${r}\n`);
|
|
185
|
-
}
|
|
186
|
-
process.stderr.write("[unerr] Uninstall complete. Data in .unerr/ preserved.\n");
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Remove unerr hook entries from Cursor's `.cursor/hooks.json`.
|
|
191
|
-
*/
|
|
192
|
-
function removeCursorHooks(cwd) {
|
|
193
|
-
const hooksPath = join(cwd, ".cursor", "hooks.json");
|
|
194
|
-
if (!existsSync(hooksPath))
|
|
195
|
-
return false;
|
|
196
|
-
try {
|
|
197
|
-
const config = JSON.parse(readFileSync(hooksPath, "utf-8"));
|
|
198
|
-
if (!Array.isArray(config.hooks))
|
|
199
|
-
return false;
|
|
200
|
-
const before = config.hooks.length;
|
|
201
|
-
config.hooks = config.hooks.filter((h) => h?.name !== "unerr-graph-tools");
|
|
202
|
-
if (config.hooks.length === before)
|
|
203
|
-
return false;
|
|
204
|
-
if (config.hooks.length === 0) {
|
|
205
|
-
unlinkSync(hooksPath);
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
writeFileSync(hooksPath, `${JSON.stringify(config, null, 2)}\n`);
|
|
209
|
-
}
|
|
210
|
-
return true;
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
return false;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Remove unerr hook scripts from Cline's `.clinerules/hooks/`.
|
|
218
|
-
*/
|
|
219
|
-
function removeClineHooks(cwd) {
|
|
220
|
-
const hookPath = join(cwd, ".clinerules", "hooks", "unerr-pre-tool.sh");
|
|
221
|
-
if (!existsSync(hookPath))
|
|
222
|
-
return false;
|
|
223
|
-
try {
|
|
224
|
-
unlinkSync(hookPath);
|
|
225
|
-
return true;
|
|
226
|
-
}
|
|
227
|
-
catch {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
}
|
package/dist/components/App.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* App — root Ink component for the interactive REPL.
|
|
4
|
-
*
|
|
5
|
-
* Manages conversation state, dispatches user input to the QueryEngine,
|
|
6
|
-
* and renders the message history with streaming responses.
|
|
7
|
-
*/
|
|
8
|
-
import { Box, Text, useApp, useInput } from "ink";
|
|
9
|
-
import { useState, useCallback } from "react";
|
|
10
|
-
import { executeQuery, } from "../core/query-engine.js";
|
|
11
|
-
import { InputBox } from "./InputBox.js";
|
|
12
|
-
import { MessageList } from "./MessageList.js";
|
|
13
|
-
import { StatusLine } from "./StatusLine.js";
|
|
14
|
-
import { ToolProgress } from "./ToolProgress.js";
|
|
15
|
-
export function App({ apiKey, chatProvider, model, systemPrompt, tools, cwd, welcomeMessage, }) {
|
|
16
|
-
const { exit } = useApp();
|
|
17
|
-
const [messages, setMessages] = useState([]);
|
|
18
|
-
const [streamingText, setStreamingText] = useState("");
|
|
19
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
20
|
-
const [activeTools, setActiveTools] = useState([]);
|
|
21
|
-
const [lastUsage, setLastUsage] = useState(null);
|
|
22
|
-
const [error, setError] = useState(null);
|
|
23
|
-
// Handle Ctrl+C to exit
|
|
24
|
-
useInput((input, key) => {
|
|
25
|
-
if (key.ctrl && input === "c") {
|
|
26
|
-
exit();
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
const handleSubmit = useCallback(async (input) => {
|
|
30
|
-
if (!input.trim())
|
|
31
|
-
return;
|
|
32
|
-
// Handle special commands
|
|
33
|
-
if (input.trim() === "/exit" || input.trim() === "/quit") {
|
|
34
|
-
exit();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
if (input.trim() === "/clear") {
|
|
38
|
-
setMessages([]);
|
|
39
|
-
setLastUsage(null);
|
|
40
|
-
setError(null);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (input.trim() === "/cost") {
|
|
44
|
-
if (lastUsage) {
|
|
45
|
-
setError(`Session: ${lastUsage.inputTokens} in / ${lastUsage.outputTokens} out — $${lastUsage.estimatedCost.toFixed(4)}`);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
setError("No usage data yet");
|
|
49
|
-
}
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const userMessage = { role: "user", content: input };
|
|
53
|
-
const updatedMessages = [...messages, userMessage];
|
|
54
|
-
setMessages(updatedMessages);
|
|
55
|
-
setIsLoading(true);
|
|
56
|
-
setStreamingText("");
|
|
57
|
-
setActiveTools([]);
|
|
58
|
-
setError(null);
|
|
59
|
-
try {
|
|
60
|
-
const options = {
|
|
61
|
-
model,
|
|
62
|
-
apiKey,
|
|
63
|
-
chatProvider,
|
|
64
|
-
tools,
|
|
65
|
-
systemPrompt,
|
|
66
|
-
toolContext: { cwd },
|
|
67
|
-
};
|
|
68
|
-
const result = await executeQuery(updatedMessages, options, {
|
|
69
|
-
onToken: (token) => {
|
|
70
|
-
setStreamingText((prev) => prev + token);
|
|
71
|
-
},
|
|
72
|
-
onToolCall: (name) => {
|
|
73
|
-
setActiveTools((prev) => [...prev, { name, status: "running" }]);
|
|
74
|
-
},
|
|
75
|
-
onToolResult: (name) => {
|
|
76
|
-
setActiveTools((prev) => prev.map((t) => t.name === name && t.status === "running"
|
|
77
|
-
? { ...t, status: "done" }
|
|
78
|
-
: t));
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
const assistantMessage = {
|
|
82
|
-
role: "assistant",
|
|
83
|
-
content: result.response,
|
|
84
|
-
toolCalls: result.toolCalls,
|
|
85
|
-
};
|
|
86
|
-
setMessages((prev) => [...prev, assistantMessage]);
|
|
87
|
-
setLastUsage(result.usage);
|
|
88
|
-
}
|
|
89
|
-
catch (err) {
|
|
90
|
-
setError(err instanceof Error ? err.message : String(err));
|
|
91
|
-
}
|
|
92
|
-
finally {
|
|
93
|
-
setIsLoading(false);
|
|
94
|
-
setStreamingText("");
|
|
95
|
-
setActiveTools([]);
|
|
96
|
-
}
|
|
97
|
-
}, [
|
|
98
|
-
messages,
|
|
99
|
-
model,
|
|
100
|
-
apiKey,
|
|
101
|
-
chatProvider,
|
|
102
|
-
tools,
|
|
103
|
-
systemPrompt,
|
|
104
|
-
cwd,
|
|
105
|
-
exit,
|
|
106
|
-
lastUsage,
|
|
107
|
-
]);
|
|
108
|
-
return (_jsxs(Box, { flexDirection: "column", width: "100%", children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "unerr" }), _jsx(Text, { color: "gray", children: " \u2014 AI assistant with code intelligence" }), _jsxs(Text, { color: "gray", children: [" (", model, ")"] })] }), welcomeMessage && messages.length === 0 && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "gray", children: welcomeMessage }) })), _jsx(MessageList, { messages: messages }), streamingText && (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "green", children: streamingText }), _jsx(Text, { color: "gray", children: "\u258A" })] })), activeTools.length > 0 && _jsx(ToolProgress, { tools: activeTools }), error && (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) })), lastUsage && _jsx(StatusLine, { usage: lastUsage }), _jsx(InputBox, { onSubmit: handleSubmit, isDisabled: isLoading })] }));
|
|
109
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* Branded banner: unerr ▸ Code intelligence for AI agents
|
|
4
|
-
*
|
|
5
|
-
* Used in startup and setup displays. Renders to stderr via Ink.
|
|
6
|
-
*/
|
|
7
|
-
import { Box, Text } from "ink";
|
|
8
|
-
import { useTheme } from "./Theme.js";
|
|
9
|
-
export function Banner() {
|
|
10
|
-
const t = useTheme();
|
|
11
|
-
return (_jsxs(Box, { marginLeft: 2, children: [_jsx(Text, { bold: true, color: t.brand, children: "unerr" }), _jsx(Text, { color: t.dim, children: " \u25B8 " }), _jsx(Text, { color: t.dim, children: "Code intelligence for your AI agents" })] }));
|
|
12
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* Inline confirm prompt: [Y/n] with context.
|
|
4
|
-
*
|
|
5
|
-
* Uses Ink's useInput() for keyboard handling.
|
|
6
|
-
* Used for entity rewind, dead code removal confirmations.
|
|
7
|
-
*/
|
|
8
|
-
import { Box, Text, useInput } from "ink";
|
|
9
|
-
import { useTheme } from "./Theme.js";
|
|
10
|
-
export function ConfirmPrompt({ message, onConfirm, defaultYes = true, }) {
|
|
11
|
-
const t = useTheme();
|
|
12
|
-
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
13
|
-
useInput((input, key) => {
|
|
14
|
-
if (input === "y" || input === "Y") {
|
|
15
|
-
onConfirm(true);
|
|
16
|
-
}
|
|
17
|
-
else if (input === "n" || input === "N") {
|
|
18
|
-
onConfirm(false);
|
|
19
|
-
}
|
|
20
|
-
else if (key.return) {
|
|
21
|
-
onConfirm(defaultYes);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
return (_jsxs(Box, { marginLeft: 2, children: [_jsxs(Text, { children: [message, " "] }), _jsx(Text, { color: t.dim, children: hint })] }));
|
|
25
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* Drift summary — modified/added/deleted counts.
|
|
4
|
-
*
|
|
5
|
-
* Used in status and startup displays.
|
|
6
|
-
*/
|
|
7
|
-
import { Box, Text } from "ink";
|
|
8
|
-
import { useTheme } from "./Theme.js";
|
|
9
|
-
export function DriftSummary({ drift }) {
|
|
10
|
-
const t = useTheme();
|
|
11
|
-
const total = drift.modified + drift.added + drift.deleted;
|
|
12
|
-
if (total === 0) {
|
|
13
|
-
return (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { color: t.dim, children: "No drift detected" }) }));
|
|
14
|
-
}
|
|
15
|
-
const parts = [];
|
|
16
|
-
if (drift.modified > 0)
|
|
17
|
-
parts.push(`${drift.modified} modified`);
|
|
18
|
-
if (drift.added > 0)
|
|
19
|
-
parts.push(`${drift.added} added`);
|
|
20
|
-
if (drift.deleted > 0)
|
|
21
|
-
parts.push(`${drift.deleted} deleted`);
|
|
22
|
-
return (_jsx(Box, { marginLeft: 4, children: _jsxs(Text, { color: t.warning, children: [total, " drifted entit", total !== 1 ? "ies" : "y", ": ", parts.join(", ")] }) }));
|
|
23
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* Colored grade badge: A, B+, C, D, F
|
|
4
|
-
*
|
|
5
|
-
* Color mapped by theme.grade() — A=green, C=yellow, F=red.
|
|
6
|
-
* Used in health card, status, first-connect displays.
|
|
7
|
-
*/
|
|
8
|
-
import { Text } from "ink";
|
|
9
|
-
import { useTheme } from "./Theme.js";
|
|
10
|
-
export function GradeBadge({ grade, score, bold = true, }) {
|
|
11
|
-
const t = useTheme();
|
|
12
|
-
const color = t.grade(grade);
|
|
13
|
-
const label = score !== undefined ? `${grade} (${score}/100)` : grade;
|
|
14
|
-
return (_jsx(Text, { bold: bold, color: color, children: label }));
|
|
15
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* Health grade card — bordered box with grade, progress bar, and top issues.
|
|
4
|
-
*
|
|
5
|
-
* Used in startup (Act 2: Revelation), status, and first-connect displays.
|
|
6
|
-
*/
|
|
7
|
-
import { Box, Text } from "ink";
|
|
8
|
-
import { GradeBadge } from "./GradeBadge.js";
|
|
9
|
-
import { ProgressBar } from "./ProgressBar.js";
|
|
10
|
-
import { useTheme } from "./Theme.js";
|
|
11
|
-
export function HealthCard({ health, compact = false, }) {
|
|
12
|
-
const t = useTheme();
|
|
13
|
-
const gradeColor = t.grade(health.grade);
|
|
14
|
-
if (compact) {
|
|
15
|
-
return (_jsxs(Box, { marginLeft: 2, children: [_jsx(GradeBadge, { grade: health.grade, score: health.score }), _jsx(Text, { children: " " }), _jsx(ProgressBar, { value: health.score / 100, width: 16, color: gradeColor }), _jsxs(Text, { color: t.dim, children: [" ", health.totalEntities, " entities \u00B7 ", health.totalEdges, " edges"] })] }));
|
|
16
|
-
}
|
|
17
|
-
return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsx(Text, { children: " " }), _jsx(GradeBadge, { grade: health.grade, score: health.score }), _jsx(Text, { children: " " }), _jsx(ProgressBar, { value: health.score / 100, width: 20, color: gradeColor, showLabel: true })] }), health.deadFunctionCount > 0 && (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: t.warning, children: ["\u26A1 ", health.deadFunctionCount, " dead function", health.deadFunctionCount !== 1 ? "s" : "", " \u2014 your agent reads these but nothing calls them"] }) })), health.highRiskEntities.map((entity) => (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: t.warning, children: ["\u26A0 ", entity.name, " \u2192 ", entity.fan_in, " caller", entity.fan_in !== 1 ? "s" : "", ", ", entity.fan_out, " callee", entity.fan_out !== 1 ? "s" : "", " (chokepoint)"] }) }, entity.name)))] }));
|
|
18
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* Animated spinner with status text.
|
|
4
|
-
*
|
|
5
|
-
* Named InkSpinner to avoid conflict with ora-based spinners.
|
|
6
|
-
* Uses Ink's useEffect for frame animation.
|
|
7
|
-
*/
|
|
8
|
-
import { Box, Text } from "ink";
|
|
9
|
-
import { useEffect, useState } from "react";
|
|
10
|
-
import { useTheme } from "./Theme.js";
|
|
11
|
-
const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
12
|
-
export function InkSpinner({ label, interval = 80, }) {
|
|
13
|
-
const t = useTheme();
|
|
14
|
-
const [frame, setFrame] = useState(0);
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
const timer = setInterval(() => {
|
|
17
|
-
setFrame((prev) => (prev + 1) % SPINNER_FRAMES.length);
|
|
18
|
-
}, interval);
|
|
19
|
-
return () => clearInterval(timer);
|
|
20
|
-
}, [interval]);
|
|
21
|
-
return (_jsxs(Box, { marginLeft: 2, children: [_jsx(Text, { color: t.info, children: SPINNER_FRAMES[frame] }), _jsxs(Text, { children: [" ", label] })] }));
|
|
22
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* InputBox — user input component with prompt indicator.
|
|
4
|
-
*/
|
|
5
|
-
import { Box, Text } from "ink";
|
|
6
|
-
import TextInput from "ink-text-input";
|
|
7
|
-
import { useState } from "react";
|
|
8
|
-
export function InputBox({ onSubmit, isDisabled }) {
|
|
9
|
-
const [value, setValue] = useState("");
|
|
10
|
-
const handleSubmit = (input) => {
|
|
11
|
-
if (isDisabled)
|
|
12
|
-
return;
|
|
13
|
-
onSubmit(input);
|
|
14
|
-
setValue("");
|
|
15
|
-
};
|
|
16
|
-
return (_jsxs(Box, { children: [_jsx(Text, { color: isDisabled ? "gray" : "cyan", bold: true, children: isDisabled ? "⏳ " : "❯ " }), isDisabled ? (_jsx(Text, { color: "gray", children: "Thinking..." })) : (_jsx(TextInput, { value: value, onChange: setValue, onSubmit: handleSubmit, placeholder: "Ask anything about your code..." }))] }));
|
|
17
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* Aligned key-value display: Label: Value
|
|
4
|
-
*
|
|
5
|
-
* Label is dimmed, value is normal. Used in status, session summary.
|
|
6
|
-
*/
|
|
7
|
-
import { Box, Text } from "ink";
|
|
8
|
-
import { useTheme } from "./Theme.js";
|
|
9
|
-
export function KeyValue({ label, value, labelWidth = 20, valueColor, }) {
|
|
10
|
-
const t = useTheme();
|
|
11
|
-
const padded = label.padEnd(labelWidth);
|
|
12
|
-
return (_jsxs(Box, { marginLeft: 4, children: [_jsx(Text, { color: t.dim, children: padded }), _jsx(Text, { color: valueColor, children: value })] }));
|
|
13
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* MessageList — renders conversation history.
|
|
4
|
-
*/
|
|
5
|
-
import { Box, Text } from "ink";
|
|
6
|
-
export function MessageList({ messages }) {
|
|
7
|
-
return (_jsx(Box, { flexDirection: "column", children: messages.map((msg, i) => (_jsx(MessageBubble, { message: msg }, `msg-${msg.role}-${i}`))) }));
|
|
8
|
-
}
|
|
9
|
-
function MessageBubble({ message }) {
|
|
10
|
-
if (message.role === "user") {
|
|
11
|
-
return (_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { bold: true, color: "blue", children: ["You:", " "] }), _jsx(Text, { children: message.content })] }));
|
|
12
|
-
}
|
|
13
|
-
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [message.toolCalls && message.toolCalls.length > 0 && (_jsx(Box, { marginBottom: 0, children: message.toolCalls.map((tc, i) => (_jsx(Box, { marginRight: 1, children: _jsxs(Text, { color: "yellow", dimColor: true, children: ["[", tc.name, "]"] }) }, `tc-${tc.name}`))) })), _jsxs(Box, { children: [_jsxs(Text, { bold: true, color: "green", children: ["unerr:", " "] }), _jsx(Text, { children: message.content })] })] }));
|
|
14
|
-
}
|