@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
package/dist/config/settings.js
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Settings Manager — user-level and project-level configuration.
|
|
3
|
-
*
|
|
4
|
-
* Hierarchy (last wins):
|
|
5
|
-
* 1. Defaults (hardcoded)
|
|
6
|
-
* 2. User settings: ~/.unerr/settings.json
|
|
7
|
-
* 3. Project settings: .unerr/settings.json
|
|
8
|
-
* 4. Environment variables: ANTHROPIC_API_KEY, UNERR_MODEL, etc.
|
|
9
|
-
*/
|
|
10
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
-
import { homedir } from "node:os";
|
|
12
|
-
import { join } from "node:path";
|
|
13
|
-
import { z } from "zod";
|
|
14
|
-
// ── Schema ────────────────────────────────────────────────────
|
|
15
|
-
const LlmProviderEnum = z.enum([
|
|
16
|
-
"ollama",
|
|
17
|
-
"lm-studio",
|
|
18
|
-
"openai-compatible",
|
|
19
|
-
"anthropic-direct",
|
|
20
|
-
]);
|
|
21
|
-
const EndpointConfigSchema = z.object({
|
|
22
|
-
provider: LlmProviderEnum.optional(),
|
|
23
|
-
baseUrl: z.string().optional(),
|
|
24
|
-
model: z.string().optional(),
|
|
25
|
-
apiKey: z.string().optional(),
|
|
26
|
-
});
|
|
27
|
-
/**
|
|
28
|
-
* BYO-LLM provider configuration for True Local Mode.
|
|
29
|
-
*
|
|
30
|
-
* Supports two usage patterns:
|
|
31
|
-
*
|
|
32
|
-
* 1. **Simple (single provider):** Set top-level `provider`, `baseUrl`, `apiKey`.
|
|
33
|
-
* Both embedding and inference use the same provider. `embeddingModel` and
|
|
34
|
-
* `chatModel` select which models to use.
|
|
35
|
-
*
|
|
36
|
-
* 2. **Split (different providers):** Set `embedding` and/or `inference` sub-objects.
|
|
37
|
-
* Each can have its own `provider`, `baseUrl`, `apiKey`, and `model`.
|
|
38
|
-
* Sub-object fields override top-level fields for that concern.
|
|
39
|
-
*
|
|
40
|
-
* Examples:
|
|
41
|
-
* - Ollama for everything: { provider: "ollama" }
|
|
42
|
-
* - Fireworks embedding + Anthropic chat:
|
|
43
|
-
* { embedding: { provider: "openai-compatible", baseUrl: "https://api.fireworks.ai/inference/v1", model: "...", apiKey: "..." },
|
|
44
|
-
* inference: { provider: "anthropic-direct", apiKey: "..." } }
|
|
45
|
-
*/
|
|
46
|
-
export const LocalLlmConfigSchema = z.object({
|
|
47
|
-
provider: LlmProviderEnum.default("ollama"),
|
|
48
|
-
baseUrl: z.string().optional(),
|
|
49
|
-
embeddingModel: z.string().default("nomic-embed-text"),
|
|
50
|
-
chatModel: z.string().default("llama3"),
|
|
51
|
-
apiKey: z.string().optional(),
|
|
52
|
-
maxConcurrency: z.number().int().min(1).default(2),
|
|
53
|
-
embeddingDimensions: z.number().int().min(1).default(384),
|
|
54
|
-
embedding: EndpointConfigSchema.optional(),
|
|
55
|
-
inference: EndpointConfigSchema.optional(),
|
|
56
|
-
});
|
|
57
|
-
/**
|
|
58
|
-
* Resolve the effective embedding endpoint config.
|
|
59
|
-
* `config.embedding` fields override top-level `config` fields.
|
|
60
|
-
*/
|
|
61
|
-
export function resolveEmbeddingEndpoint(config) {
|
|
62
|
-
const e = config.embedding;
|
|
63
|
-
return {
|
|
64
|
-
provider: e?.provider ?? config.provider,
|
|
65
|
-
baseUrl: e?.baseUrl ?? config.baseUrl,
|
|
66
|
-
model: e?.model ?? config.embeddingModel,
|
|
67
|
-
apiKey: e?.apiKey ?? config.apiKey,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Resolve the effective inference (chat) endpoint config.
|
|
72
|
-
* `config.inference` fields override top-level `config` fields.
|
|
73
|
-
*/
|
|
74
|
-
export function resolveInferenceEndpoint(config) {
|
|
75
|
-
const i = config.inference;
|
|
76
|
-
return {
|
|
77
|
-
provider: i?.provider ?? config.provider,
|
|
78
|
-
baseUrl: i?.baseUrl ?? config.baseUrl,
|
|
79
|
-
model: i?.model ?? config.chatModel,
|
|
80
|
-
apiKey: i?.apiKey ?? config.apiKey,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
const LlmConfigSchema = z.object({
|
|
84
|
-
provider: z
|
|
85
|
-
.enum(["anthropic", "openai", "google", "ollama", "openai-compatible"])
|
|
86
|
-
.default("anthropic"),
|
|
87
|
-
model: z.string().default("claude-sonnet-4-20250514"),
|
|
88
|
-
apiKey: z.string().optional(),
|
|
89
|
-
baseUrl: z.string().optional(),
|
|
90
|
-
});
|
|
91
|
-
export const SettingsSchema = z.object({
|
|
92
|
-
/** Default Claude model for interactive sessions */
|
|
93
|
-
model: z.string().default("claude-sonnet-4-20250514"),
|
|
94
|
-
/** Anthropic API key (prefer env var ANTHROPIC_API_KEY) */
|
|
95
|
-
anthropicApiKey: z.string().optional(),
|
|
96
|
-
/** Permission mode for tool execution */
|
|
97
|
-
permissionMode: z.enum(["prompt", "auto", "deny-all"]).default("prompt"),
|
|
98
|
-
/** Maximum output tokens per LLM turn */
|
|
99
|
-
maxTokens: z.number().default(8192),
|
|
100
|
-
/** Enable verbose logging */
|
|
101
|
-
verbose: z.boolean().default(false),
|
|
102
|
-
/** AI SDK LLM configuration (Sprint D — unified multi-provider) */
|
|
103
|
-
llm: LlmConfigSchema.optional(),
|
|
104
|
-
/** BYO-LLM configuration for local LLM providers */
|
|
105
|
-
localLlm: LocalLlmConfigSchema.optional(),
|
|
106
|
-
});
|
|
107
|
-
// ── Defaults ──────────────────────────────────────────────────
|
|
108
|
-
const DEFAULTS = SettingsSchema.parse({});
|
|
109
|
-
// ── Loader ────────────────────────────────────────────────────
|
|
110
|
-
function loadJsonFile(filePath) {
|
|
111
|
-
if (!existsSync(filePath))
|
|
112
|
-
return {};
|
|
113
|
-
try {
|
|
114
|
-
return JSON.parse(readFileSync(filePath, "utf-8"));
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return {};
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Load merged settings from all layers.
|
|
122
|
-
*/
|
|
123
|
-
export function loadSettings(cwd) {
|
|
124
|
-
const projectDir = cwd ?? process.cwd();
|
|
125
|
-
// Layer 2: User settings
|
|
126
|
-
const userSettings = loadJsonFile(join(homedir(), ".unerr", "settings.json"));
|
|
127
|
-
// Layer 3: Project settings
|
|
128
|
-
const projectSettings = loadJsonFile(join(projectDir, ".unerr", "settings.json"));
|
|
129
|
-
// Layer 4: Environment overrides
|
|
130
|
-
const envOverrides = {};
|
|
131
|
-
if (process.env.ANTHROPIC_API_KEY)
|
|
132
|
-
envOverrides.anthropicApiKey = process.env.ANTHROPIC_API_KEY;
|
|
133
|
-
if (process.env.UNERR_MODEL)
|
|
134
|
-
envOverrides.model = process.env.UNERR_MODEL;
|
|
135
|
-
if (process.env.UNERR_VERBOSE === "true")
|
|
136
|
-
envOverrides.verbose = true;
|
|
137
|
-
// AI SDK LLM env overrides (Sprint D)
|
|
138
|
-
if (process.env.UNERR_LLM_PROVIDER) {
|
|
139
|
-
envOverrides.llm = {
|
|
140
|
-
provider: process.env.UNERR_LLM_PROVIDER,
|
|
141
|
-
...(process.env.UNERR_MODEL && { model: process.env.UNERR_MODEL }),
|
|
142
|
-
...(process.env.UNERR_LLM_API_KEY && {
|
|
143
|
-
apiKey: process.env.UNERR_LLM_API_KEY,
|
|
144
|
-
}),
|
|
145
|
-
...(process.env.UNERR_LLM_BASE_URL && {
|
|
146
|
-
baseUrl: process.env.UNERR_LLM_BASE_URL,
|
|
147
|
-
}),
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
// BYO-LLM env overrides
|
|
151
|
-
if (process.env.UNERR_LOCAL_LLM_PROVIDER)
|
|
152
|
-
envOverrides.localLlm = {
|
|
153
|
-
...projectSettings.localLlm,
|
|
154
|
-
...userSettings.localLlm,
|
|
155
|
-
provider: process.env.UNERR_LOCAL_LLM_PROVIDER,
|
|
156
|
-
...(process.env.UNERR_LOCAL_LLM_BASE_URL && {
|
|
157
|
-
baseUrl: process.env.UNERR_LOCAL_LLM_BASE_URL,
|
|
158
|
-
}),
|
|
159
|
-
...(process.env.UNERR_LOCAL_LLM_EMBEDDING_MODEL && {
|
|
160
|
-
embeddingModel: process.env.UNERR_LOCAL_LLM_EMBEDDING_MODEL,
|
|
161
|
-
}),
|
|
162
|
-
...(process.env.UNERR_LOCAL_LLM_CHAT_MODEL && {
|
|
163
|
-
chatModel: process.env.UNERR_LOCAL_LLM_CHAT_MODEL,
|
|
164
|
-
}),
|
|
165
|
-
};
|
|
166
|
-
// Merge: defaults ← user ← project ← env
|
|
167
|
-
const merged = {
|
|
168
|
-
...DEFAULTS,
|
|
169
|
-
...userSettings,
|
|
170
|
-
...projectSettings,
|
|
171
|
-
...envOverrides,
|
|
172
|
-
};
|
|
173
|
-
return SettingsSchema.parse(merged);
|
|
174
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI Tool Auto-Detection — detects installed AI coding tools in a project.
|
|
3
|
-
*
|
|
4
|
-
* Registry-driven: scans directory markers and environment variables
|
|
5
|
-
* from agent-registry.ts to identify all AI tools present.
|
|
6
|
-
*
|
|
7
|
-
* Returns all detected tools so `unerr init` can configure each one.
|
|
8
|
-
*/
|
|
9
|
-
import { existsSync } from "node:fs";
|
|
10
|
-
import { join } from "node:path";
|
|
11
|
-
import { AGENT_REGISTRY } from "./agent-registry.js";
|
|
12
|
-
/**
|
|
13
|
-
* Detect all AI coding tools present in the project directory.
|
|
14
|
-
* Checks directory markers and environment variables from the agent registry.
|
|
15
|
-
*/
|
|
16
|
-
export function detectTools(cwd) {
|
|
17
|
-
const detected = [];
|
|
18
|
-
for (const agent of AGENT_REGISTRY) {
|
|
19
|
-
// Check directory markers
|
|
20
|
-
const hasDirMarker = agent.dirMarkers.some((dir) => existsSync(join(cwd, dir)));
|
|
21
|
-
// Check environment variables
|
|
22
|
-
const hasEnvVar = agent.envVars.some((envVar) => !!process.env[envVar]);
|
|
23
|
-
if (hasDirMarker || hasEnvVar) {
|
|
24
|
-
const configPath = join(cwd, agent.projectConfigPath);
|
|
25
|
-
detected.push({
|
|
26
|
-
ide: agent.id,
|
|
27
|
-
configDir: join(cwd, agent.dirMarkers[0] ?? ""),
|
|
28
|
-
hasExistingConfig: existsSync(configPath),
|
|
29
|
-
agent,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return detected;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Get a human-readable summary of detected tools.
|
|
37
|
-
*/
|
|
38
|
-
export function formatDetectedTools(tools) {
|
|
39
|
-
if (tools.length === 0)
|
|
40
|
-
return "No AI tools detected";
|
|
41
|
-
return tools.map((t) => t.agent.name).join(", ");
|
|
42
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Value Surfacing — guard formatter, scorecard, and counterfactual explanation.
|
|
3
|
-
*
|
|
4
|
-
* S8.1: Guard fires when session dollar savings exceed threshold.
|
|
5
|
-
* S8.3: Session scorecard formats final session metrics.
|
|
6
|
-
* S8.7: Counterfactual explanation: "Without unerr: ~XK tokens -> with unerr: YK tokens"
|
|
7
|
-
*/
|
|
8
|
-
const DEFAULT_CONFIG = {
|
|
9
|
-
guardThresholdDollars: 0.5,
|
|
10
|
-
weeklyEnabled: true,
|
|
11
|
-
scorecardEnabled: true,
|
|
12
|
-
counterfactualEnabled: true,
|
|
13
|
-
modelId: "claude-sonnet-4-20250514",
|
|
14
|
-
};
|
|
15
|
-
let currentConfig = { ...DEFAULT_CONFIG };
|
|
16
|
-
export function getValueSurfacingConfig() {
|
|
17
|
-
return { ...currentConfig };
|
|
18
|
-
}
|
|
19
|
-
export function setValueSurfacingConfig(overrides) {
|
|
20
|
-
currentConfig = { ...currentConfig, ...overrides };
|
|
21
|
-
}
|
|
22
|
-
export function resetValueSurfacingConfig() {
|
|
23
|
-
currentConfig = { ...DEFAULT_CONFIG };
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Creates a session-scoped guard that fires once when dollar savings threshold is crossed.
|
|
27
|
-
*/
|
|
28
|
-
export function createValueGuard(thresholdDollars) {
|
|
29
|
-
const threshold = thresholdDollars ?? currentConfig.guardThresholdDollars;
|
|
30
|
-
const state = { fired: false, lastFiredAt: 0 };
|
|
31
|
-
/**
|
|
32
|
-
* Check if the guard should fire. Returns the formatted message or null.
|
|
33
|
-
*/
|
|
34
|
-
function check(sessionDollarsSaved) {
|
|
35
|
-
if (state.fired)
|
|
36
|
-
return null;
|
|
37
|
-
if (sessionDollarsSaved < threshold)
|
|
38
|
-
return null;
|
|
39
|
-
state.fired = true;
|
|
40
|
-
state.lastFiredAt = Date.now();
|
|
41
|
-
return formatGuardMessage(sessionDollarsSaved);
|
|
42
|
-
}
|
|
43
|
-
function hasFired() {
|
|
44
|
-
return state.fired;
|
|
45
|
-
}
|
|
46
|
-
function reset() {
|
|
47
|
-
state.fired = false;
|
|
48
|
-
state.lastFiredAt = 0;
|
|
49
|
-
}
|
|
50
|
-
return { check, hasFired, reset };
|
|
51
|
-
}
|
|
52
|
-
function formatGuardMessage(dollarsSaved) {
|
|
53
|
-
return `unerr saved $${dollarsSaved.toFixed(2)} this session`;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Format a session scorecard from raw metrics.
|
|
57
|
-
*/
|
|
58
|
-
export function formatScorecard(input) {
|
|
59
|
-
const intelligence = [];
|
|
60
|
-
if (input.blastRadiusComputed > 0) {
|
|
61
|
-
intelligence.push(`${input.blastRadiusComputed} blast radius computation${input.blastRadiusComputed !== 1 ? "s" : ""}`);
|
|
62
|
-
}
|
|
63
|
-
if (input.conventionsInjected > 0) {
|
|
64
|
-
intelligence.push(`${input.conventionsInjected} convention injection${input.conventionsInjected !== 1 ? "s" : ""}`);
|
|
65
|
-
}
|
|
66
|
-
if (input.outputsCompressed > 0) {
|
|
67
|
-
intelligence.push(`${input.outputsCompressed} output${input.outputsCompressed !== 1 ? "s" : ""} compressed`);
|
|
68
|
-
}
|
|
69
|
-
if (input.correctionsApplied > 0) {
|
|
70
|
-
intelligence.push(`${input.correctionsApplied} correction${input.correctionsApplied !== 1 ? "s" : ""} applied`);
|
|
71
|
-
}
|
|
72
|
-
if (input.wrongApproachesPrevented > 0) {
|
|
73
|
-
intelligence.push(`${input.wrongApproachesPrevented} wrong approach${input.wrongApproachesPrevented !== 1 ? "es" : ""} prevented`);
|
|
74
|
-
}
|
|
75
|
-
const durationMin = Math.round(input.durationMs / 60_000);
|
|
76
|
-
return {
|
|
77
|
-
toolCalls: input.toolCalls,
|
|
78
|
-
tokensSaved: formatTokens(input.tokensSaved),
|
|
79
|
-
dollarsSaved: `$${input.dollarsSaved.toFixed(2)}`,
|
|
80
|
-
efficiency: `${Math.round(input.efficiency)}%`,
|
|
81
|
-
duration: durationMin > 0 ? `${durationMin} min` : "<1 min",
|
|
82
|
-
intelligenceApplied: intelligence,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
// ── S8.7: Counterfactual Explanation ────────────────────────────────
|
|
86
|
-
/**
|
|
87
|
-
* Build counterfactual explanation string.
|
|
88
|
-
* "Without unerr: ~XK tokens -> with unerr: YK tokens (Z% reduction)"
|
|
89
|
-
*/
|
|
90
|
-
export function formatCounterfactual(tokensWithout, tokensWith) {
|
|
91
|
-
const withoutStr = formatTokens(tokensWithout);
|
|
92
|
-
const withStr = formatTokens(tokensWith);
|
|
93
|
-
const reduction = tokensWithout > 0
|
|
94
|
-
? Math.round(((tokensWithout - tokensWith) / tokensWithout) * 100)
|
|
95
|
-
: 0;
|
|
96
|
-
return `Without unerr: ~${withoutStr} tokens \u2192 with unerr: ${withStr} tokens (${reduction}% reduction)`;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Assemble value meta fields for a single response.
|
|
100
|
-
*/
|
|
101
|
-
export function assembleValueMeta(tokensSaved, dollarSavings, optimizationDescription) {
|
|
102
|
-
const meta = {
|
|
103
|
-
tokens_saved: tokensSaved,
|
|
104
|
-
dollar_savings: Math.round(dollarSavings * 1_000_000) / 1_000_000,
|
|
105
|
-
powered_by: "unerr \u2014 intelligent token optimization",
|
|
106
|
-
};
|
|
107
|
-
if (optimizationDescription) {
|
|
108
|
-
meta.optimization = optimizationDescription;
|
|
109
|
-
}
|
|
110
|
-
return meta;
|
|
111
|
-
}
|
|
112
|
-
// ── Shared Utilities ────────────────────────────────────────────────
|
|
113
|
-
function formatTokens(n) {
|
|
114
|
-
if (n >= 1_000_000)
|
|
115
|
-
return `${(n / 1_000_000).toFixed(1)}M`;
|
|
116
|
-
if (n >= 1_000)
|
|
117
|
-
return `${(n / 1_000).toFixed(1)}K`;
|
|
118
|
-
return String(n);
|
|
119
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Context Assembler — builds the system prompt for the interactive assistant.
|
|
3
|
-
*
|
|
4
|
-
* This is unerr's key differentiator: the system prompt includes graph-powered
|
|
5
|
-
* intelligence about the codebase — conventions, high-risk entities, business context,
|
|
6
|
-
* architecture overview — that no other coding assistant can provide without manual
|
|
7
|
-
* CLAUDE.md authoring.
|
|
8
|
-
*
|
|
9
|
-
* Context layers:
|
|
10
|
-
* 1. Environment: OS, shell, Node version, git branch
|
|
11
|
-
* 2. Project: package.json, README, file structure summary
|
|
12
|
-
* 3. Intelligence: conventions, risk entities, community structure (from CozoDB graph)
|
|
13
|
-
* 4. Memory: .unerr/memory.md or equivalent persistent context
|
|
14
|
-
*/
|
|
15
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
16
|
-
import { platform, release } from "node:os";
|
|
17
|
-
import { basename, join } from "node:path";
|
|
18
|
-
import { getCurrentBranch } from "../utils/git.js";
|
|
19
|
-
// ── Environment Context ───────────────────────────────────────
|
|
20
|
-
async function getEnvironmentContext(cwd) {
|
|
21
|
-
const os = `${platform()} ${release()}`;
|
|
22
|
-
const shell = process.env.SHELL ?? "unknown";
|
|
23
|
-
const nodeVersion = process.version;
|
|
24
|
-
const gitBranch = (await getCurrentBranch(cwd)) ?? "unknown";
|
|
25
|
-
return {
|
|
26
|
-
name: "Environment",
|
|
27
|
-
content: [
|
|
28
|
-
`OS: ${os}`,
|
|
29
|
-
`Shell: ${shell}`,
|
|
30
|
-
`Node: ${nodeVersion}`,
|
|
31
|
-
`Working directory: ${cwd}`,
|
|
32
|
-
`Git branch: ${gitBranch}`,
|
|
33
|
-
].join("\n"),
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
// ── Project Context ───────────────────────────────────────────
|
|
37
|
-
function getProjectContext(cwd) {
|
|
38
|
-
const lines = [];
|
|
39
|
-
// package.json
|
|
40
|
-
const pkgPath = join(cwd, "package.json");
|
|
41
|
-
if (existsSync(pkgPath)) {
|
|
42
|
-
try {
|
|
43
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
44
|
-
lines.push(`Project: ${pkg.name ?? basename(cwd)} v${pkg.version ?? "0.0.0"}`);
|
|
45
|
-
if (pkg.description)
|
|
46
|
-
lines.push(`Description: ${pkg.description}`);
|
|
47
|
-
if (pkg.scripts)
|
|
48
|
-
lines.push(`Scripts: ${Object.keys(pkg.scripts).join(", ")}`);
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// Malformed package.json
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// README presence
|
|
55
|
-
for (const name of ["README.md", "readme.md", "README"]) {
|
|
56
|
-
if (existsSync(join(cwd, name))) {
|
|
57
|
-
lines.push(`README: ${name} exists`);
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return lines.length > 0
|
|
62
|
-
? { name: "Project", content: lines.join("\n") }
|
|
63
|
-
: null;
|
|
64
|
-
}
|
|
65
|
-
// ── Graph Intelligence Context (the differentiator) ───────────
|
|
66
|
-
/**
|
|
67
|
-
* Build intelligence context from the local CozoDB graph.
|
|
68
|
-
*
|
|
69
|
-
* TODO: Implement graph queries for:
|
|
70
|
-
* - Top conventions and adherence rates (get_conventions)
|
|
71
|
-
* - High-risk entities with blast radius (fan_in > threshold)
|
|
72
|
-
* - Business context for key modules
|
|
73
|
-
* - Community/feature structure
|
|
74
|
-
*/
|
|
75
|
-
async function getIntelligenceContext(_graph) {
|
|
76
|
-
// TODO: Query the graph for conventions, risk entities, architecture overview
|
|
77
|
-
// This is what makes unerr's assistant unique — the LLM starts with codebase knowledge
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Assemble the full system prompt from all context layers.
|
|
82
|
-
*/
|
|
83
|
-
export async function assembleContext(opts) {
|
|
84
|
-
const sections = [];
|
|
85
|
-
// Layer 1: Environment
|
|
86
|
-
sections.push(await getEnvironmentContext(opts.cwd));
|
|
87
|
-
// Layer 2: Project
|
|
88
|
-
const project = getProjectContext(opts.cwd);
|
|
89
|
-
if (project)
|
|
90
|
-
sections.push(project);
|
|
91
|
-
// Layer 3: Graph intelligence (unerr's moat)
|
|
92
|
-
if (opts.graph) {
|
|
93
|
-
const intelligence = await getIntelligenceContext(opts.graph);
|
|
94
|
-
if (intelligence)
|
|
95
|
-
sections.push(intelligence);
|
|
96
|
-
}
|
|
97
|
-
// Layer 4: Additional instructions
|
|
98
|
-
if (opts.additionalInstructions) {
|
|
99
|
-
sections.push({
|
|
100
|
-
name: "Instructions",
|
|
101
|
-
content: opts.additionalInstructions,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
const systemPrompt = sections
|
|
105
|
-
.map((s) => `# ${s.name}\n${s.content}`)
|
|
106
|
-
.join("\n\n---\n\n");
|
|
107
|
-
return { systemPrompt, sections };
|
|
108
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conversation Manager — in-memory conversation history with optional persistence.
|
|
3
|
-
*
|
|
4
|
-
* Manages the message list for the interactive REPL session.
|
|
5
|
-
* Supports context window management (truncation when approaching limits).
|
|
6
|
-
*/
|
|
7
|
-
export class Conversation {
|
|
8
|
-
messages = [];
|
|
9
|
-
maxMessages;
|
|
10
|
-
constructor(opts = {}) {
|
|
11
|
-
this.maxMessages = opts.maxMessages ?? 100;
|
|
12
|
-
}
|
|
13
|
-
/** Add a message to the conversation. */
|
|
14
|
-
add(message) {
|
|
15
|
-
this.messages.push(message);
|
|
16
|
-
// Evict oldest messages (always keep at least the last user message)
|
|
17
|
-
while (this.messages.length > this.maxMessages) {
|
|
18
|
-
this.messages.shift();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
/** Get all messages in chronological order. */
|
|
22
|
-
getMessages() {
|
|
23
|
-
return [...this.messages];
|
|
24
|
-
}
|
|
25
|
-
/** Clear conversation history. */
|
|
26
|
-
clear() {
|
|
27
|
-
this.messages = [];
|
|
28
|
-
}
|
|
29
|
-
/** Get the number of messages. */
|
|
30
|
-
get length() {
|
|
31
|
-
return this.messages.length;
|
|
32
|
-
}
|
|
33
|
-
}
|