@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/daemon/client.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* unerrd client — communicates with the daemon supervisor over UDS.
|
|
3
|
-
*
|
|
4
|
-
* Used by `unerr --mcp` (bridge) and CLI commands to interact with `unerrd`.
|
|
5
|
-
* All methods are fire-and-forget except `ensureRepo` which waits for the
|
|
6
|
-
* repo process to become ready (returns the per-repo UDS sock path).
|
|
7
|
-
*
|
|
8
|
-
* Protocol: newline-delimited JSON over `~/.unerr/unerrd.sock`.
|
|
9
|
-
* Each request is a single connection (connect → send → read → close).
|
|
10
|
-
*/
|
|
11
|
-
import { createConnection } from "node:net";
|
|
12
|
-
import { join } from "node:path";
|
|
13
|
-
import { globalDir } from "./registry.js";
|
|
14
|
-
/** Default path to the daemon's UDS control socket. */
|
|
15
|
-
export function daemonSockPath() {
|
|
16
|
-
return join(globalDir(), "unerrd.sock");
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Send a single request to unerrd and return the parsed response.
|
|
20
|
-
* Opens a fresh connection per request (control-plane traffic is low-frequency).
|
|
21
|
-
*/
|
|
22
|
-
export function sendRequest(sockPath, request, timeoutMs = 30_000) {
|
|
23
|
-
return new Promise((resolve, reject) => {
|
|
24
|
-
let buffer = "";
|
|
25
|
-
let settled = false;
|
|
26
|
-
const timer = setTimeout(() => {
|
|
27
|
-
if (settled)
|
|
28
|
-
return;
|
|
29
|
-
settled = true;
|
|
30
|
-
socket.destroy();
|
|
31
|
-
reject(new Error(`unerrd request timed out after ${timeoutMs}ms`));
|
|
32
|
-
}, timeoutMs);
|
|
33
|
-
timer.unref();
|
|
34
|
-
const socket = createConnection(sockPath);
|
|
35
|
-
socket.on("connect", () => {
|
|
36
|
-
socket.write(`${JSON.stringify(request)}\n`);
|
|
37
|
-
});
|
|
38
|
-
socket.on("data", (chunk) => {
|
|
39
|
-
buffer += chunk.toString();
|
|
40
|
-
const newlineIdx = buffer.indexOf("\n");
|
|
41
|
-
if (newlineIdx === -1)
|
|
42
|
-
return;
|
|
43
|
-
const line = buffer.slice(0, newlineIdx).trim();
|
|
44
|
-
if (!line)
|
|
45
|
-
return;
|
|
46
|
-
if (settled)
|
|
47
|
-
return;
|
|
48
|
-
settled = true;
|
|
49
|
-
clearTimeout(timer);
|
|
50
|
-
socket.destroy();
|
|
51
|
-
try {
|
|
52
|
-
resolve(JSON.parse(line));
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
reject(new Error(`Invalid JSON from unerrd: ${line.slice(0, 200)}`));
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
socket.on("error", (err) => {
|
|
59
|
-
if (settled)
|
|
60
|
-
return;
|
|
61
|
-
settled = true;
|
|
62
|
-
clearTimeout(timer);
|
|
63
|
-
reject(err);
|
|
64
|
-
});
|
|
65
|
-
socket.on("close", () => {
|
|
66
|
-
if (settled)
|
|
67
|
-
return;
|
|
68
|
-
settled = true;
|
|
69
|
-
clearTimeout(timer);
|
|
70
|
-
reject(new Error("unerrd connection closed before response"));
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Send a fire-and-forget request (no response needed).
|
|
76
|
-
* Used for `activity` which the daemon acknowledges with no response (null).
|
|
77
|
-
*/
|
|
78
|
-
export function sendFireAndForget(sockPath, request) {
|
|
79
|
-
try {
|
|
80
|
-
const socket = createConnection(sockPath);
|
|
81
|
-
socket.on("connect", () => {
|
|
82
|
-
socket.write(`${JSON.stringify(request)}\n`);
|
|
83
|
-
// Give the socket a moment to flush, then destroy
|
|
84
|
-
setTimeout(() => socket.destroy(), 50);
|
|
85
|
-
});
|
|
86
|
-
socket.on("error", () => {
|
|
87
|
-
// Best-effort — daemon might be shutting down
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
// Best-effort
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// ── High-level client methods ─────────────────────────────────────
|
|
95
|
-
/**
|
|
96
|
-
* Ensure a repo process is running. Returns the per-repo UDS sock path.
|
|
97
|
-
* If the repo is already running, returns immediately.
|
|
98
|
-
* If not, the supervisor spawns it and waits for ready.
|
|
99
|
-
*/
|
|
100
|
-
export async function ensureRepo(sockPath, repoPath) {
|
|
101
|
-
const resp = await sendRequest(sockPath, { cmd: "ensure", repo: repoPath });
|
|
102
|
-
if (!resp.ok) {
|
|
103
|
-
throw new Error(`ensureRepo failed: ${resp.error}`);
|
|
104
|
-
}
|
|
105
|
-
return resp.sock;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Register a bridge connection to a repo.
|
|
109
|
-
* Increments the repo's connection count (prevents idle sweep).
|
|
110
|
-
*/
|
|
111
|
-
export async function connectRepo(sockPath, repoPath) {
|
|
112
|
-
const resp = await sendRequest(sockPath, { cmd: "connect", repo: repoPath });
|
|
113
|
-
if (!resp.ok) {
|
|
114
|
-
throw new Error(`connectRepo failed: ${resp.error}`);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Unregister a bridge connection from a repo.
|
|
119
|
-
* Decrements the repo's connection count.
|
|
120
|
-
*/
|
|
121
|
-
export async function disconnectRepo(sockPath, repoPath) {
|
|
122
|
-
const resp = await sendRequest(sockPath, {
|
|
123
|
-
cmd: "disconnect",
|
|
124
|
-
repo: repoPath,
|
|
125
|
-
});
|
|
126
|
-
if (!resp.ok) {
|
|
127
|
-
throw new Error(`disconnectRepo failed: ${resp.error}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/** Fire-and-forget activity ping. Does not wait for response. */
|
|
131
|
-
export function sendActivity(sockPath, repoPath) {
|
|
132
|
-
sendFireAndForget(sockPath, { cmd: "activity", repo: repoPath });
|
|
133
|
-
}
|
|
134
|
-
/** Get status of all managed repos. */
|
|
135
|
-
export async function getStatus(sockPath) {
|
|
136
|
-
const resp = await sendRequest(sockPath, { cmd: "status" });
|
|
137
|
-
if (!resp.ok) {
|
|
138
|
-
throw new Error(`getStatus failed: ${resp.error}`);
|
|
139
|
-
}
|
|
140
|
-
return resp;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Check if the daemon socket is reachable (probe connection).
|
|
144
|
-
* Returns true if connection succeeds, false otherwise.
|
|
145
|
-
*/
|
|
146
|
-
export function probeDaemon(sockPath) {
|
|
147
|
-
return new Promise((resolve) => {
|
|
148
|
-
const socket = createConnection(sockPath);
|
|
149
|
-
const timer = setTimeout(() => {
|
|
150
|
-
socket.destroy();
|
|
151
|
-
resolve(false);
|
|
152
|
-
}, 1000);
|
|
153
|
-
timer.unref();
|
|
154
|
-
socket.on("connect", () => {
|
|
155
|
-
clearTimeout(timer);
|
|
156
|
-
socket.destroy();
|
|
157
|
-
resolve(true);
|
|
158
|
-
});
|
|
159
|
-
socket.on("error", () => {
|
|
160
|
-
clearTimeout(timer);
|
|
161
|
-
resolve(false);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
}
|
package/dist/daemon/detect-ci.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CI / container detection — prevents daemon side-effects in ephemeral environments.
|
|
3
|
-
*
|
|
4
|
-
* Used by:
|
|
5
|
-
* - Auto-install gating (skip platform service installation)
|
|
6
|
-
* - Bridge auto-spawn (skip unerrd launch in CI)
|
|
7
|
-
* - Warm-start scheduler (skip boot-time warm-up)
|
|
8
|
-
*
|
|
9
|
-
* Detection covers all major CI providers + container runtimes.
|
|
10
|
-
*/
|
|
11
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
12
|
-
let cachedResult = null;
|
|
13
|
-
/**
|
|
14
|
-
* Returns true if running in a CI environment or container.
|
|
15
|
-
* Result is cached for the process lifetime.
|
|
16
|
-
*/
|
|
17
|
-
export function isCI() {
|
|
18
|
-
if (cachedResult !== null)
|
|
19
|
-
return cachedResult;
|
|
20
|
-
cachedResult = detect();
|
|
21
|
-
return cachedResult;
|
|
22
|
-
}
|
|
23
|
-
/** Reset cache (for testing). */
|
|
24
|
-
export function resetCICache() {
|
|
25
|
-
cachedResult = null;
|
|
26
|
-
}
|
|
27
|
-
function detect() {
|
|
28
|
-
// Generic CI env (set by most providers)
|
|
29
|
-
if (env("CI"))
|
|
30
|
-
return true;
|
|
31
|
-
if (env("CONTINUOUS_INTEGRATION"))
|
|
32
|
-
return true;
|
|
33
|
-
if (env("BUILD_NUMBER"))
|
|
34
|
-
return true;
|
|
35
|
-
// Major CI providers
|
|
36
|
-
if (env("GITHUB_ACTIONS"))
|
|
37
|
-
return true;
|
|
38
|
-
if (env("GITLAB_CI"))
|
|
39
|
-
return true;
|
|
40
|
-
if (env("CIRCLECI"))
|
|
41
|
-
return true;
|
|
42
|
-
if (env("BUILDKITE"))
|
|
43
|
-
return true;
|
|
44
|
-
if (env("JENKINS_URL"))
|
|
45
|
-
return true;
|
|
46
|
-
if (env("TRAVIS"))
|
|
47
|
-
return true;
|
|
48
|
-
if (env("CODEBUILD_BUILD_ID"))
|
|
49
|
-
return true;
|
|
50
|
-
if (env("TF_BUILD"))
|
|
51
|
-
return true;
|
|
52
|
-
if (env("BITBUCKET_PIPELINE_UUID"))
|
|
53
|
-
return true;
|
|
54
|
-
if (env("DRONE"))
|
|
55
|
-
return true;
|
|
56
|
-
if (env("WOODPECKER_CI"))
|
|
57
|
-
return true;
|
|
58
|
-
if (env("TEAMCITY_VERSION"))
|
|
59
|
-
return true;
|
|
60
|
-
if (env("HEROKU_TEST_RUN_ID"))
|
|
61
|
-
return true;
|
|
62
|
-
// Container detection
|
|
63
|
-
if (existsSync("/.dockerenv"))
|
|
64
|
-
return true;
|
|
65
|
-
try {
|
|
66
|
-
const cgroup = readFileSync("/proc/1/cgroup", "utf-8");
|
|
67
|
-
if (cgroup.includes("docker") ||
|
|
68
|
-
cgroup.includes("kubepods") ||
|
|
69
|
-
cgroup.includes("containerd")) {
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
// Not on Linux or no permission — fine
|
|
75
|
-
}
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
function env(name) {
|
|
79
|
-
const v = process.env[name];
|
|
80
|
-
return v !== undefined && v !== "" && v !== "0" && v !== "false";
|
|
81
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Linux auto-start — systemd user unit for unerrd.
|
|
3
|
-
*
|
|
4
|
-
* Generates ~/.config/systemd/user/unerrd.service.
|
|
5
|
-
* Enables with `systemctl --user enable --now`.
|
|
6
|
-
* Runs `loginctl enable-linger` for headless/server boxes.
|
|
7
|
-
* Skips WSL (no boot phase).
|
|
8
|
-
*/
|
|
9
|
-
import { execSync } from "node:child_process";
|
|
10
|
-
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
11
|
-
import { homedir } from "node:os";
|
|
12
|
-
import { join } from "node:path";
|
|
13
|
-
const UNIT_NAME = "unerrd.service";
|
|
14
|
-
function unitDir() {
|
|
15
|
-
return join(homedir(), ".config", "systemd", "user");
|
|
16
|
-
}
|
|
17
|
-
function unitPath() {
|
|
18
|
-
return join(unitDir(), UNIT_NAME);
|
|
19
|
-
}
|
|
20
|
-
function resolveUnerrBin() {
|
|
21
|
-
try {
|
|
22
|
-
return execSync("which unerr", { encoding: "utf-8" }).trim();
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return join(process.argv[1] || "unerr");
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function isWSL() {
|
|
29
|
-
try {
|
|
30
|
-
const version = readFileSync("/proc/version", "utf-8");
|
|
31
|
-
return version.toLowerCase().includes("microsoft");
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function generateUnit(bin) {
|
|
38
|
-
return `[Unit]
|
|
39
|
-
Description=unerr daemon supervisor
|
|
40
|
-
After=network.target
|
|
41
|
-
|
|
42
|
-
[Service]
|
|
43
|
-
Type=simple
|
|
44
|
-
ExecStart=${bin} daemon start --foreground
|
|
45
|
-
Restart=on-failure
|
|
46
|
-
RestartSec=5
|
|
47
|
-
Environment=HOME=${homedir()}
|
|
48
|
-
Environment=PATH=${process.env.PATH || "/usr/local/bin:/usr/bin:/bin"}
|
|
49
|
-
|
|
50
|
-
[Install]
|
|
51
|
-
WantedBy=default.target
|
|
52
|
-
`;
|
|
53
|
-
}
|
|
54
|
-
export function installSystemd() {
|
|
55
|
-
const path = unitPath();
|
|
56
|
-
if (isWSL()) {
|
|
57
|
-
return {
|
|
58
|
-
installed: false,
|
|
59
|
-
path,
|
|
60
|
-
error: "WSL detected — systemd user units have no boot phase. Use Windows auto-start instead.",
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
const bin = resolveUnerrBin();
|
|
65
|
-
const dir = unitDir();
|
|
66
|
-
mkdirSync(dir, { recursive: true });
|
|
67
|
-
writeFileSync(path, generateUnit(bin), "utf-8");
|
|
68
|
-
execSync("systemctl --user daemon-reload", { stdio: "ignore" });
|
|
69
|
-
execSync("systemctl --user enable --now unerrd.service", {
|
|
70
|
-
stdio: "ignore",
|
|
71
|
-
});
|
|
72
|
-
// Enable lingering so the unit starts at boot, not just at first login
|
|
73
|
-
try {
|
|
74
|
-
execSync("loginctl enable-linger $USER", { stdio: "ignore" });
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
// loginctl may not be available (containers, minimal installs)
|
|
78
|
-
}
|
|
79
|
-
return { installed: true, path };
|
|
80
|
-
}
|
|
81
|
-
catch (err) {
|
|
82
|
-
return {
|
|
83
|
-
installed: false,
|
|
84
|
-
path,
|
|
85
|
-
error: err instanceof Error ? err.message : String(err),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
export function uninstallSystemd() {
|
|
90
|
-
const path = unitPath();
|
|
91
|
-
try {
|
|
92
|
-
try {
|
|
93
|
-
execSync("systemctl --user disable --now unerrd.service", {
|
|
94
|
-
stdio: "ignore",
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
// Not enabled
|
|
99
|
-
}
|
|
100
|
-
if (existsSync(path))
|
|
101
|
-
unlinkSync(path);
|
|
102
|
-
try {
|
|
103
|
-
execSync("systemctl --user daemon-reload", { stdio: "ignore" });
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
// Best-effort
|
|
107
|
-
}
|
|
108
|
-
return { installed: false, path };
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
return {
|
|
112
|
-
installed: false,
|
|
113
|
-
path,
|
|
114
|
-
error: err instanceof Error ? err.message : String(err),
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
export function isSystemdInstalled() {
|
|
119
|
-
return existsSync(unitPath());
|
|
120
|
-
}
|
|
121
|
-
export function getSystemdStatus() {
|
|
122
|
-
const unitExists = existsSync(unitPath());
|
|
123
|
-
let active = false;
|
|
124
|
-
let enabled = false;
|
|
125
|
-
if (unitExists) {
|
|
126
|
-
try {
|
|
127
|
-
const out = execSync("systemctl --user is-active unerrd.service", {
|
|
128
|
-
encoding: "utf-8",
|
|
129
|
-
}).trim();
|
|
130
|
-
active = out === "active";
|
|
131
|
-
}
|
|
132
|
-
catch {
|
|
133
|
-
// inactive or failed
|
|
134
|
-
}
|
|
135
|
-
try {
|
|
136
|
-
const out = execSync("systemctl --user is-enabled unerrd.service", {
|
|
137
|
-
encoding: "utf-8",
|
|
138
|
-
}).trim();
|
|
139
|
-
enabled = out === "enabled";
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
// not enabled
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return { unitExists, active, enabled };
|
|
146
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* macOS auto-start — launchd plist for unerrd.
|
|
3
|
-
*
|
|
4
|
-
* Generates and installs ~/Library/LaunchAgents/com.unerr.daemon.plist.
|
|
5
|
-
* KeepAlive on crash, RunAtLoad=true, user-scoped (no sudo).
|
|
6
|
-
* Loaded via `launchctl bootstrap gui/<uid>`.
|
|
7
|
-
*/
|
|
8
|
-
import { execSync } from "node:child_process";
|
|
9
|
-
import { existsSync, mkdirSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
10
|
-
import { homedir } from "node:os";
|
|
11
|
-
import { join } from "node:path";
|
|
12
|
-
const PLIST_NAME = "com.unerr.daemon.plist";
|
|
13
|
-
function plistDir() {
|
|
14
|
-
return join(homedir(), "Library", "LaunchAgents");
|
|
15
|
-
}
|
|
16
|
-
function plistPath() {
|
|
17
|
-
return join(plistDir(), PLIST_NAME);
|
|
18
|
-
}
|
|
19
|
-
function logPath() {
|
|
20
|
-
return join(homedir(), ".unerr", "logs", "unerrd.boot.log");
|
|
21
|
-
}
|
|
22
|
-
function resolveUnerrBin() {
|
|
23
|
-
try {
|
|
24
|
-
return execSync("which unerr", { encoding: "utf-8" }).trim();
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
return join(process.argv[1] || "unerr");
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function generatePlist(bin) {
|
|
31
|
-
const log = logPath();
|
|
32
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
33
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
34
|
-
<plist version="1.0">
|
|
35
|
-
<dict>
|
|
36
|
-
<key>Label</key>
|
|
37
|
-
<string>com.unerr.daemon</string>
|
|
38
|
-
<key>ProgramArguments</key>
|
|
39
|
-
<array>
|
|
40
|
-
<string>${bin}</string>
|
|
41
|
-
<string>daemon</string>
|
|
42
|
-
<string>start</string>
|
|
43
|
-
<string>--foreground</string>
|
|
44
|
-
</array>
|
|
45
|
-
<key>RunAtLoad</key>
|
|
46
|
-
<true/>
|
|
47
|
-
<key>KeepAlive</key>
|
|
48
|
-
<dict>
|
|
49
|
-
<key>SuccessfulExit</key>
|
|
50
|
-
<false/>
|
|
51
|
-
</dict>
|
|
52
|
-
<key>StandardOutPath</key>
|
|
53
|
-
<string>${log}</string>
|
|
54
|
-
<key>StandardErrorPath</key>
|
|
55
|
-
<string>${log}</string>
|
|
56
|
-
<key>ProcessType</key>
|
|
57
|
-
<string>Background</string>
|
|
58
|
-
<key>LowPriorityBackgroundIO</key>
|
|
59
|
-
<true/>
|
|
60
|
-
</dict>
|
|
61
|
-
</plist>`;
|
|
62
|
-
}
|
|
63
|
-
export function installLaunchd() {
|
|
64
|
-
const dir = plistDir();
|
|
65
|
-
const path = plistPath();
|
|
66
|
-
const bin = resolveUnerrBin();
|
|
67
|
-
try {
|
|
68
|
-
mkdirSync(dir, { recursive: true });
|
|
69
|
-
const logDir = join(homedir(), ".unerr", "logs");
|
|
70
|
-
mkdirSync(logDir, { recursive: true });
|
|
71
|
-
const plist = generatePlist(bin);
|
|
72
|
-
writeFileSync(path, plist, "utf-8");
|
|
73
|
-
const uid = process.getuid?.() ?? execSync("id -u", { encoding: "utf-8" }).trim();
|
|
74
|
-
// Unload first if previously loaded (idempotent)
|
|
75
|
-
try {
|
|
76
|
-
execSync(`launchctl bootout gui/${uid}/${PLIST_NAME.replace(".plist", "")}`, {
|
|
77
|
-
stdio: "ignore",
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
// Not loaded — fine
|
|
82
|
-
}
|
|
83
|
-
execSync(`launchctl bootstrap gui/${uid} "${path}"`, { stdio: "ignore" });
|
|
84
|
-
return { installed: true, path };
|
|
85
|
-
}
|
|
86
|
-
catch (err) {
|
|
87
|
-
return {
|
|
88
|
-
installed: false,
|
|
89
|
-
path,
|
|
90
|
-
error: err instanceof Error ? err.message : String(err),
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
export function uninstallLaunchd() {
|
|
95
|
-
const path = plistPath();
|
|
96
|
-
try {
|
|
97
|
-
const uid = process.getuid?.() ?? execSync("id -u", { encoding: "utf-8" }).trim();
|
|
98
|
-
try {
|
|
99
|
-
execSync(`launchctl bootout gui/${uid}/${PLIST_NAME.replace(".plist", "")}`, {
|
|
100
|
-
stdio: "ignore",
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
catch {
|
|
104
|
-
// Not loaded
|
|
105
|
-
}
|
|
106
|
-
if (existsSync(path))
|
|
107
|
-
unlinkSync(path);
|
|
108
|
-
return { installed: false, path };
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
return {
|
|
112
|
-
installed: false,
|
|
113
|
-
path,
|
|
114
|
-
error: err instanceof Error ? err.message : String(err),
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
export function isLaunchdInstalled() {
|
|
119
|
-
return existsSync(plistPath());
|
|
120
|
-
}
|
|
121
|
-
export function getLaunchdStatus() {
|
|
122
|
-
const plistExists = existsSync(plistPath());
|
|
123
|
-
let loaded = false;
|
|
124
|
-
if (plistExists) {
|
|
125
|
-
try {
|
|
126
|
-
const out = execSync("launchctl list", { encoding: "utf-8" });
|
|
127
|
-
loaded = out.includes("com.unerr.daemon");
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
// launchctl failed
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return { loaded, plistExists };
|
|
134
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Windows auto-start — two-path approach.
|
|
3
|
-
*
|
|
4
|
-
* (a) Preferred: Scheduled Task `Unerr Daemon` via schtasks.
|
|
5
|
-
* (b) Fallback: .cmd shim in %APPDATA%\...\Startup.
|
|
6
|
-
*
|
|
7
|
-
* Both run as current user (no admin).
|
|
8
|
-
*/
|
|
9
|
-
import { execSync } from "node:child_process";
|
|
10
|
-
import { existsSync, mkdirSync, unlinkSync, writeFileSync } from "node:fs";
|
|
11
|
-
import { homedir } from "node:os";
|
|
12
|
-
import { join } from "node:path";
|
|
13
|
-
const TASK_NAME = "Unerr Daemon";
|
|
14
|
-
const STARTUP_CMD_NAME = "unerrd.cmd";
|
|
15
|
-
function startupDir() {
|
|
16
|
-
return join(process.env.APPDATA || join(homedir(), "AppData", "Roaming"), "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
|
|
17
|
-
}
|
|
18
|
-
function startupCmdPath() {
|
|
19
|
-
return join(startupDir(), STARTUP_CMD_NAME);
|
|
20
|
-
}
|
|
21
|
-
function resolveUnerrBin() {
|
|
22
|
-
try {
|
|
23
|
-
return (execSync("where unerr", { encoding: "utf-8" })
|
|
24
|
-
.trim()
|
|
25
|
-
.split("\n")[0]
|
|
26
|
-
?.trim() ?? "unerr");
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
return process.argv[1] || "unerr";
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
export function installWindows() {
|
|
33
|
-
const bin = resolveUnerrBin();
|
|
34
|
-
// Attempt scheduled task first
|
|
35
|
-
const taskResult = installScheduledTask(bin);
|
|
36
|
-
if (taskResult.installed)
|
|
37
|
-
return taskResult;
|
|
38
|
-
// Fallback to startup folder
|
|
39
|
-
return installStartupCmd(bin);
|
|
40
|
-
}
|
|
41
|
-
function installScheduledTask(bin) {
|
|
42
|
-
const cmd = `"${bin}" daemon start --foreground`;
|
|
43
|
-
try {
|
|
44
|
-
// Delete existing task first (idempotent)
|
|
45
|
-
try {
|
|
46
|
-
execSync(`schtasks /Delete /TN "${TASK_NAME}" /F`, { stdio: "ignore" });
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
// Didn't exist
|
|
50
|
-
}
|
|
51
|
-
execSync(`schtasks /Create /SC ONLOGON /TN "${TASK_NAME}" /TR ${cmd} /RI 5 /DU 0000:00 /F`, { stdio: "ignore" });
|
|
52
|
-
return { installed: true, path: `Scheduled Task: ${TASK_NAME}` };
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
return {
|
|
56
|
-
installed: false,
|
|
57
|
-
path: `Scheduled Task: ${TASK_NAME}`,
|
|
58
|
-
error: "schtasks unavailable — falling back to Startup folder",
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function installStartupCmd(bin) {
|
|
63
|
-
const path = startupCmdPath();
|
|
64
|
-
try {
|
|
65
|
-
const dir = startupDir();
|
|
66
|
-
mkdirSync(dir, { recursive: true });
|
|
67
|
-
const script = `@echo off\r\n"${bin}" daemon start --foreground\r\n`;
|
|
68
|
-
writeFileSync(path, script, "utf-8");
|
|
69
|
-
return { installed: true, path };
|
|
70
|
-
}
|
|
71
|
-
catch (err) {
|
|
72
|
-
return {
|
|
73
|
-
installed: false,
|
|
74
|
-
path,
|
|
75
|
-
error: err instanceof Error ? err.message : String(err),
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
export function uninstallWindows() {
|
|
80
|
-
const errors = [];
|
|
81
|
-
// Remove scheduled task
|
|
82
|
-
try {
|
|
83
|
-
execSync(`schtasks /Delete /TN "${TASK_NAME}" /F`, { stdio: "ignore" });
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
// Didn't exist
|
|
87
|
-
}
|
|
88
|
-
// Remove startup cmd
|
|
89
|
-
const cmdPath = startupCmdPath();
|
|
90
|
-
try {
|
|
91
|
-
if (existsSync(cmdPath))
|
|
92
|
-
unlinkSync(cmdPath);
|
|
93
|
-
}
|
|
94
|
-
catch (err) {
|
|
95
|
-
errors.push(err instanceof Error ? err.message : String(err));
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
installed: false,
|
|
99
|
-
path: cmdPath,
|
|
100
|
-
error: errors.length > 0 ? errors.join("; ") : undefined,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
export function isWindowsInstalled() {
|
|
104
|
-
// Check scheduled task
|
|
105
|
-
try {
|
|
106
|
-
execSync(`schtasks /Query /TN "${TASK_NAME}" /FO CSV /NH`, {
|
|
107
|
-
stdio: "pipe",
|
|
108
|
-
});
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
// Not a scheduled task
|
|
113
|
-
}
|
|
114
|
-
// Check startup cmd
|
|
115
|
-
return existsSync(startupCmdPath());
|
|
116
|
-
}
|