@neat.is/core 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +359 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +2 -1
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +354 -6
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -745,6 +745,7 @@ __export(cli_exports, {
|
|
|
745
745
|
resolveDaemonUrl: () => resolveDaemonUrl,
|
|
746
746
|
resolveProjectForVerb: () => resolveProjectForVerb,
|
|
747
747
|
runInit: () => runInit,
|
|
748
|
+
runMonitorVerb: () => runMonitorVerb,
|
|
748
749
|
runQueryVerb: () => runQueryVerb,
|
|
749
750
|
runSkill: () => runSkill,
|
|
750
751
|
usage: () => usage2
|
|
@@ -18211,8 +18212,8 @@ async function healthIsForProject(restPort, project) {
|
|
|
18211
18212
|
}
|
|
18212
18213
|
return false;
|
|
18213
18214
|
}
|
|
18214
|
-
function daemonLogPath(
|
|
18215
|
-
return import_node_path67.default.join(
|
|
18215
|
+
function daemonLogPath(projectPath3) {
|
|
18216
|
+
return import_node_path67.default.join(projectPath3, "neat-out", "daemon.log");
|
|
18216
18217
|
}
|
|
18217
18218
|
function spawnDaemonDetached(spec) {
|
|
18218
18219
|
const here = import_node_path67.default.dirname((0, import_node_url4.fileURLToPath)(importMetaUrl));
|
|
@@ -19078,9 +19079,9 @@ async function runHooksCommand(args) {
|
|
|
19078
19079
|
}
|
|
19079
19080
|
}
|
|
19080
19081
|
|
|
19081
|
-
// src/
|
|
19082
|
+
// src/monitor.ts
|
|
19082
19083
|
init_cjs_shims();
|
|
19083
|
-
var
|
|
19084
|
+
var import_types62 = require("@neat.is/types");
|
|
19084
19085
|
|
|
19085
19086
|
// src/cli-client.ts
|
|
19086
19087
|
init_cjs_shims();
|
|
@@ -19613,7 +19614,311 @@ async function pushSnapshotToRemote(input) {
|
|
|
19613
19614
|
);
|
|
19614
19615
|
}
|
|
19615
19616
|
|
|
19617
|
+
// src/monitor.ts
|
|
19618
|
+
var OBSERVED_DEP_EDGE_TYPES = /* @__PURE__ */ new Set([
|
|
19619
|
+
import_types62.EdgeType.CALLS,
|
|
19620
|
+
import_types62.EdgeType.CONNECTS_TO,
|
|
19621
|
+
import_types62.EdgeType.PUBLISHES_TO,
|
|
19622
|
+
import_types62.EdgeType.CONSUMES_FROM
|
|
19623
|
+
]);
|
|
19624
|
+
function divergenceKey(d) {
|
|
19625
|
+
const column = "column" in d && d.column ? d.column : "";
|
|
19626
|
+
const edgeType = "edgeType" in d && d.edgeType ? d.edgeType : "";
|
|
19627
|
+
let extra = "";
|
|
19628
|
+
switch (d.type) {
|
|
19629
|
+
case "version-mismatch":
|
|
19630
|
+
extra = `${d.extractedVersion}->${d.observedVersion}`;
|
|
19631
|
+
break;
|
|
19632
|
+
case "host-mismatch":
|
|
19633
|
+
extra = `${d.extractedHost}->${d.observedHost}`;
|
|
19634
|
+
break;
|
|
19635
|
+
case "compat-violation":
|
|
19636
|
+
extra = `${d.rule.kind}:${d.rule.package ?? ""}`;
|
|
19637
|
+
break;
|
|
19638
|
+
default:
|
|
19639
|
+
extra = "";
|
|
19640
|
+
}
|
|
19641
|
+
return `div|${d.type}|${d.source}|${d.target}|${edgeType}|${column}|${extra}`;
|
|
19642
|
+
}
|
|
19643
|
+
function tableLabel(d) {
|
|
19644
|
+
return "table" in d && d.table ? d.table : d.source;
|
|
19645
|
+
}
|
|
19646
|
+
function formatDivergenceLine2(d) {
|
|
19647
|
+
switch (d.type) {
|
|
19648
|
+
case "missing-observed":
|
|
19649
|
+
if (d.column) {
|
|
19650
|
+
return `\u26A0 divergence [missing-observed] ${tableLabel(d)}.${d.column} declared, never observed in production`;
|
|
19651
|
+
}
|
|
19652
|
+
return `\u26A0 divergence [missing-observed] ${d.source} \u2192 ${d.target} declared, never observed in production`;
|
|
19653
|
+
case "missing-extracted":
|
|
19654
|
+
if (d.column) {
|
|
19655
|
+
return `\u26A0 divergence [missing-extracted] production writes ${tableLabel(d)}.${d.column} \u2014 not declared in code`;
|
|
19656
|
+
}
|
|
19657
|
+
return `\u26A0 divergence [missing-extracted] production ${d.source} \u2192 ${d.target} \u2014 not declared in code`;
|
|
19658
|
+
case "version-mismatch":
|
|
19659
|
+
return `\u26A0 divergence [version-mismatch] ${d.source} \u2192 ${d.target} declared ${d.extractedVersion}, observed ${d.observedVersion} (${d.compatibility})`;
|
|
19660
|
+
case "host-mismatch":
|
|
19661
|
+
return `\u26A0 divergence [host-mismatch] ${d.source} \u2192 ${d.target} declared host ${d.extractedHost}, observed host ${d.observedHost}`;
|
|
19662
|
+
case "compat-violation":
|
|
19663
|
+
return `\u26A0 divergence [compat-violation] ${d.source} \u2192 ${d.target} \u2014 ${d.rule.kind}${d.rule.package ? ` (${d.rule.package})` : ""}`;
|
|
19664
|
+
}
|
|
19665
|
+
}
|
|
19666
|
+
function formatStaleLine(edgeId) {
|
|
19667
|
+
const parsed = (0, import_types62.parseEdgeId)(edgeId);
|
|
19668
|
+
if (parsed) {
|
|
19669
|
+
return `\u22EF stale ${parsed.source} \u2192 ${parsed.target} (observed edge went quiet)`;
|
|
19670
|
+
}
|
|
19671
|
+
return `\u22EF stale ${edgeId} (observed edge went quiet)`;
|
|
19672
|
+
}
|
|
19673
|
+
function formatObservedEdgeLine(edge) {
|
|
19674
|
+
return `+ observed ${edge.source} \u2192 ${edge.target} (new runtime dependency)`;
|
|
19675
|
+
}
|
|
19676
|
+
function divergenceJson(d) {
|
|
19677
|
+
return JSON.stringify({ kind: "divergence", ...d });
|
|
19678
|
+
}
|
|
19679
|
+
function staleJson(edgeId) {
|
|
19680
|
+
const parsed = (0, import_types62.parseEdgeId)(edgeId);
|
|
19681
|
+
return JSON.stringify({
|
|
19682
|
+
kind: "stale",
|
|
19683
|
+
edgeId,
|
|
19684
|
+
...parsed ? { source: parsed.source, target: parsed.target, edgeType: parsed.type } : {}
|
|
19685
|
+
});
|
|
19686
|
+
}
|
|
19687
|
+
function observedEdgeJson(edge) {
|
|
19688
|
+
return JSON.stringify({
|
|
19689
|
+
kind: "observed",
|
|
19690
|
+
id: edge.id,
|
|
19691
|
+
source: edge.source,
|
|
19692
|
+
target: edge.target,
|
|
19693
|
+
edgeType: edge.type,
|
|
19694
|
+
provenance: edge.provenance
|
|
19695
|
+
});
|
|
19696
|
+
}
|
|
19697
|
+
var MonitorEmitter = class {
|
|
19698
|
+
constructor(opts) {
|
|
19699
|
+
this.opts = opts;
|
|
19700
|
+
}
|
|
19701
|
+
opts;
|
|
19702
|
+
seen = /* @__PURE__ */ new Set();
|
|
19703
|
+
out(line) {
|
|
19704
|
+
this.opts.write(line + "\n");
|
|
19705
|
+
}
|
|
19706
|
+
// Emit every not-yet-seen divergence in a fresh result. Returns the count
|
|
19707
|
+
// newly emitted (0 → nothing printed, the silent path). Idempotent across
|
|
19708
|
+
// re-reads: the seen-set keys off divergenceKey.
|
|
19709
|
+
emitDivergences(result) {
|
|
19710
|
+
let emitted = 0;
|
|
19711
|
+
for (const d of result.divergences) {
|
|
19712
|
+
const key = divergenceKey(d);
|
|
19713
|
+
if (this.seen.has(key)) continue;
|
|
19714
|
+
this.seen.add(key);
|
|
19715
|
+
this.out(this.opts.json ? divergenceJson(d) : formatDivergenceLine2(d));
|
|
19716
|
+
emitted++;
|
|
19717
|
+
}
|
|
19718
|
+
return emitted;
|
|
19719
|
+
}
|
|
19720
|
+
// Emit a stale-transition once, keyed on the edge id.
|
|
19721
|
+
emitStale(edgeId) {
|
|
19722
|
+
const key = `stale|${edgeId}`;
|
|
19723
|
+
if (this.seen.has(key)) return false;
|
|
19724
|
+
this.seen.add(key);
|
|
19725
|
+
this.out(this.opts.json ? staleJson(edgeId) : formatStaleLine(edgeId));
|
|
19726
|
+
return true;
|
|
19727
|
+
}
|
|
19728
|
+
// Emit a new OBSERVED runtime dependency once, keyed on the edge id. Silently
|
|
19729
|
+
// ignores non-OBSERVED edges and non-dependency edge types (structural
|
|
19730
|
+
// ownership), so only real runtime dependencies reach stdout.
|
|
19731
|
+
emitObservedEdge(edge) {
|
|
19732
|
+
if (edge.provenance !== import_types62.Provenance.OBSERVED) return false;
|
|
19733
|
+
if (!OBSERVED_DEP_EDGE_TYPES.has(edge.type)) return false;
|
|
19734
|
+
const key = `edge|${edge.id}`;
|
|
19735
|
+
if (this.seen.has(key)) return false;
|
|
19736
|
+
this.seen.add(key);
|
|
19737
|
+
this.out(this.opts.json ? observedEdgeJson(edge) : formatObservedEdgeLine(edge));
|
|
19738
|
+
return true;
|
|
19739
|
+
}
|
|
19740
|
+
};
|
|
19741
|
+
function parseFrame(raw) {
|
|
19742
|
+
let event = "message";
|
|
19743
|
+
const dataLines = [];
|
|
19744
|
+
for (const line of raw.split("\n")) {
|
|
19745
|
+
if (line.length === 0 || line.startsWith(":")) continue;
|
|
19746
|
+
if (line.startsWith("event:")) {
|
|
19747
|
+
event = line.slice("event:".length).trim();
|
|
19748
|
+
} else if (line.startsWith("data:")) {
|
|
19749
|
+
dataLines.push(line.slice("data:".length).replace(/^ /, ""));
|
|
19750
|
+
}
|
|
19751
|
+
}
|
|
19752
|
+
if (dataLines.length === 0) return null;
|
|
19753
|
+
return { event, data: dataLines.join("\n") };
|
|
19754
|
+
}
|
|
19755
|
+
async function drainSse(body, onFrame) {
|
|
19756
|
+
const reader = body.getReader();
|
|
19757
|
+
const decoder = new TextDecoder();
|
|
19758
|
+
let buf = "";
|
|
19759
|
+
try {
|
|
19760
|
+
for (; ; ) {
|
|
19761
|
+
const { done, value } = await reader.read();
|
|
19762
|
+
if (done) break;
|
|
19763
|
+
buf += decoder.decode(value, { stream: true });
|
|
19764
|
+
buf = buf.replace(/\r\n/g, "\n");
|
|
19765
|
+
let idx;
|
|
19766
|
+
while ((idx = buf.indexOf("\n\n")) !== -1) {
|
|
19767
|
+
const rawFrame = buf.slice(0, idx);
|
|
19768
|
+
buf = buf.slice(idx + 2);
|
|
19769
|
+
const frame = parseFrame(rawFrame);
|
|
19770
|
+
if (frame) onFrame(frame);
|
|
19771
|
+
}
|
|
19772
|
+
}
|
|
19773
|
+
} finally {
|
|
19774
|
+
try {
|
|
19775
|
+
reader.releaseLock();
|
|
19776
|
+
} catch {
|
|
19777
|
+
}
|
|
19778
|
+
}
|
|
19779
|
+
}
|
|
19780
|
+
function safeParse(data) {
|
|
19781
|
+
try {
|
|
19782
|
+
return JSON.parse(data);
|
|
19783
|
+
} catch {
|
|
19784
|
+
return null;
|
|
19785
|
+
}
|
|
19786
|
+
}
|
|
19787
|
+
function projectPath2(project, suffix) {
|
|
19788
|
+
if (!project) return suffix;
|
|
19789
|
+
return `/projects/${encodeURIComponent(project)}${suffix}`;
|
|
19790
|
+
}
|
|
19791
|
+
function backoffDelay(attempt, capMs) {
|
|
19792
|
+
return Math.min(capMs, 500 * 2 ** Math.min(attempt, 6));
|
|
19793
|
+
}
|
|
19794
|
+
async function runMonitor(opts) {
|
|
19795
|
+
const write = opts.write ?? ((line) => process.stdout.write(line));
|
|
19796
|
+
const debounceMs = opts.debounceMs ?? 400;
|
|
19797
|
+
const backoffCapMs = opts.backoffCapMs ?? 1e4;
|
|
19798
|
+
const maxReconnects = opts.maxReconnects ?? Number.POSITIVE_INFINITY;
|
|
19799
|
+
const client = createHttpClient(opts.baseUrl, opts.authToken);
|
|
19800
|
+
const emitter = new MonitorEmitter({ json: opts.json, write });
|
|
19801
|
+
const divergencesPath = projectPath2(opts.project, "/graph/divergences");
|
|
19802
|
+
const eventsUrl = `${opts.baseUrl.replace(/\/$/, "")}${projectPath2(opts.project, "/events")}`;
|
|
19803
|
+
let readTimer = null;
|
|
19804
|
+
let reading = false;
|
|
19805
|
+
let readPending = false;
|
|
19806
|
+
const doRead = async () => {
|
|
19807
|
+
if (reading) {
|
|
19808
|
+
readPending = true;
|
|
19809
|
+
return;
|
|
19810
|
+
}
|
|
19811
|
+
reading = true;
|
|
19812
|
+
try {
|
|
19813
|
+
const result = await client.get(divergencesPath);
|
|
19814
|
+
emitter.emitDivergences(result);
|
|
19815
|
+
} catch {
|
|
19816
|
+
} finally {
|
|
19817
|
+
reading = false;
|
|
19818
|
+
if (readPending) {
|
|
19819
|
+
readPending = false;
|
|
19820
|
+
scheduleRead();
|
|
19821
|
+
}
|
|
19822
|
+
}
|
|
19823
|
+
};
|
|
19824
|
+
const scheduleRead = () => {
|
|
19825
|
+
if (readTimer) clearTimeout(readTimer);
|
|
19826
|
+
readTimer = setTimeout(() => {
|
|
19827
|
+
readTimer = null;
|
|
19828
|
+
void doRead();
|
|
19829
|
+
}, debounceMs);
|
|
19830
|
+
if (typeof readTimer.unref === "function") readTimer.unref();
|
|
19831
|
+
};
|
|
19832
|
+
const onFrame = (frame) => {
|
|
19833
|
+
switch (frame.event) {
|
|
19834
|
+
case "extraction-complete":
|
|
19835
|
+
scheduleRead();
|
|
19836
|
+
break;
|
|
19837
|
+
case "stale-transition": {
|
|
19838
|
+
const payload = safeParse(frame.data);
|
|
19839
|
+
const edgeId = payload && typeof payload.edgeId === "string" ? payload.edgeId : void 0;
|
|
19840
|
+
if (edgeId) emitter.emitStale(edgeId);
|
|
19841
|
+
scheduleRead();
|
|
19842
|
+
break;
|
|
19843
|
+
}
|
|
19844
|
+
case "edge-added": {
|
|
19845
|
+
const payload = safeParse(frame.data);
|
|
19846
|
+
const edge = payload?.edge;
|
|
19847
|
+
if (edge && edge.provenance === import_types62.Provenance.OBSERVED) {
|
|
19848
|
+
emitter.emitObservedEdge(edge);
|
|
19849
|
+
scheduleRead();
|
|
19850
|
+
}
|
|
19851
|
+
break;
|
|
19852
|
+
}
|
|
19853
|
+
default:
|
|
19854
|
+
break;
|
|
19855
|
+
}
|
|
19856
|
+
};
|
|
19857
|
+
const headers = { accept: "text/event-stream" };
|
|
19858
|
+
if (opts.authToken && opts.authToken.length > 0) {
|
|
19859
|
+
headers.authorization = `Bearer ${opts.authToken}`;
|
|
19860
|
+
}
|
|
19861
|
+
let connectedOnce = false;
|
|
19862
|
+
let firstConnect = true;
|
|
19863
|
+
for (let attempt = 0; ; attempt++) {
|
|
19864
|
+
if (opts.signal?.aborted) break;
|
|
19865
|
+
let res;
|
|
19866
|
+
try {
|
|
19867
|
+
res = await fetch(eventsUrl, { headers, signal: opts.signal });
|
|
19868
|
+
} catch (err) {
|
|
19869
|
+
if (err.name === "AbortError") break;
|
|
19870
|
+
if (!connectedOnce || attempt >= maxReconnects) break;
|
|
19871
|
+
await sleep(backoffDelay(attempt, backoffCapMs), opts.signal);
|
|
19872
|
+
continue;
|
|
19873
|
+
}
|
|
19874
|
+
if (!res.ok || !res.body) {
|
|
19875
|
+
await res.body?.cancel().catch(() => {
|
|
19876
|
+
});
|
|
19877
|
+
if (!connectedOnce || attempt >= maxReconnects) break;
|
|
19878
|
+
await sleep(backoffDelay(attempt, backoffCapMs), opts.signal);
|
|
19879
|
+
continue;
|
|
19880
|
+
}
|
|
19881
|
+
connectedOnce = true;
|
|
19882
|
+
attempt = 0;
|
|
19883
|
+
if (firstConnect) {
|
|
19884
|
+
firstConnect = false;
|
|
19885
|
+
await doRead();
|
|
19886
|
+
} else {
|
|
19887
|
+
scheduleRead();
|
|
19888
|
+
}
|
|
19889
|
+
try {
|
|
19890
|
+
await drainSse(res.body, onFrame);
|
|
19891
|
+
} catch {
|
|
19892
|
+
}
|
|
19893
|
+
if (opts.signal?.aborted) break;
|
|
19894
|
+
if (attempt >= maxReconnects) break;
|
|
19895
|
+
await sleep(backoffDelay(attempt, backoffCapMs), opts.signal);
|
|
19896
|
+
}
|
|
19897
|
+
if (readTimer) clearTimeout(readTimer);
|
|
19898
|
+
return 0;
|
|
19899
|
+
}
|
|
19900
|
+
function sleep(ms, signal) {
|
|
19901
|
+
return new Promise((resolve) => {
|
|
19902
|
+
if (signal?.aborted) {
|
|
19903
|
+
resolve();
|
|
19904
|
+
return;
|
|
19905
|
+
}
|
|
19906
|
+
const timer = setTimeout(() => {
|
|
19907
|
+
signal?.removeEventListener("abort", onAbort);
|
|
19908
|
+
resolve();
|
|
19909
|
+
}, ms);
|
|
19910
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
19911
|
+
const onAbort = () => {
|
|
19912
|
+
clearTimeout(timer);
|
|
19913
|
+
resolve();
|
|
19914
|
+
};
|
|
19915
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
19916
|
+
});
|
|
19917
|
+
}
|
|
19918
|
+
|
|
19616
19919
|
// src/cli-verbs.ts
|
|
19920
|
+
init_cjs_shims();
|
|
19921
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
19617
19922
|
async function resolveProjectEntry(opts) {
|
|
19618
19923
|
const entries = await listProjects();
|
|
19619
19924
|
if (opts.project) {
|
|
@@ -19776,7 +20081,7 @@ async function runSync(opts) {
|
|
|
19776
20081
|
}
|
|
19777
20082
|
|
|
19778
20083
|
// src/cli.ts
|
|
19779
|
-
var
|
|
20084
|
+
var import_types63 = require("@neat.is/types");
|
|
19780
20085
|
function isNpxInvocation() {
|
|
19781
20086
|
if (process.env.npm_command === "exec") return true;
|
|
19782
20087
|
const execpath = process.env.npm_execpath ?? "";
|
|
@@ -19807,6 +20112,14 @@ function usage2() {
|
|
|
19807
20112
|
console.log(" watch <path> Start neat-core, watch <path>, re-extract on changes.");
|
|
19808
20113
|
console.log(" PORT (default 8080), OTEL_PORT (4318), HOST (0.0.0.0)");
|
|
19809
20114
|
console.log(" control listeners. NEAT_OTLP_GRPC=true also opens 4317.");
|
|
20115
|
+
console.log(" monitor Stream live graph facts to stdout \u2014 one line per new");
|
|
20116
|
+
console.log(" fact \u2014 as the daemon learns them: fresh divergences,");
|
|
20117
|
+
console.log(" integrations that just went stale, and new observed");
|
|
20118
|
+
console.log(" runtime dependencies. Silent when nothing is new; exits");
|
|
20119
|
+
console.log(" clean with no output when no daemon is reachable.");
|
|
20120
|
+
console.log(" Flags:");
|
|
20121
|
+
console.log(" --project <name> watch a registered project by name");
|
|
20122
|
+
console.log(" --json emit one JSON object per line");
|
|
19810
20123
|
console.log(" list Report the daemons running on this machine (alias: ps).");
|
|
19811
20124
|
console.log(" Reads ~/.neat/daemons/ and folds in any registered");
|
|
19812
20125
|
console.log(" project no daemon has self-described yet.");
|
|
@@ -20466,14 +20779,14 @@ async function main() {
|
|
|
20466
20779
|
console.error(`neat uninstall: no project named "${name}"`);
|
|
20467
20780
|
process.exit(1);
|
|
20468
20781
|
}
|
|
20469
|
-
const
|
|
20782
|
+
const projectPath3 = daemon?.record.projectPath ?? removed?.path ?? "(unknown path)";
|
|
20470
20783
|
if (daemon) {
|
|
20471
20784
|
if (daemon.live && signalDaemonStop(daemon.record.pid)) {
|
|
20472
20785
|
console.log(`uninstall: ${name} \u2014 stopped daemon pid ${daemon.record.pid}`);
|
|
20473
20786
|
}
|
|
20474
20787
|
await removeDaemonRecord(daemon.source);
|
|
20475
20788
|
}
|
|
20476
|
-
console.log(`unregistered: ${name} (${
|
|
20789
|
+
console.log(`unregistered: ${name} (${projectPath3})`);
|
|
20477
20790
|
console.log("note: neat-out/, policy.json, and other files at the project path were left in place.");
|
|
20478
20791
|
return;
|
|
20479
20792
|
}
|
|
@@ -20528,6 +20841,11 @@ async function main() {
|
|
|
20528
20841
|
if (result.exitCode !== 0) process.exit(result.exitCode);
|
|
20529
20842
|
return;
|
|
20530
20843
|
}
|
|
20844
|
+
if (cmd === "monitor") {
|
|
20845
|
+
const code = await runMonitorVerb(parsed);
|
|
20846
|
+
if (code !== 0) process.exit(code);
|
|
20847
|
+
return;
|
|
20848
|
+
}
|
|
20531
20849
|
if (QUERY_VERBS.has(cmd)) {
|
|
20532
20850
|
const code = await runQueryVerb(cmd, parsed);
|
|
20533
20851
|
if (code !== 0) process.exit(code);
|
|
@@ -20736,10 +21054,10 @@ async function runQueryVerb(cmd, parsed) {
|
|
|
20736
21054
|
const parts = parsed.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
20737
21055
|
const out = [];
|
|
20738
21056
|
for (const p of parts) {
|
|
20739
|
-
const r =
|
|
21057
|
+
const r = import_types63.DivergenceTypeSchema.safeParse(p);
|
|
20740
21058
|
if (!r.success) {
|
|
20741
21059
|
console.error(
|
|
20742
|
-
`neat divergences: unknown --type "${p}". allowed: ${
|
|
21060
|
+
`neat divergences: unknown --type "${p}". allowed: ${import_types63.DivergenceTypeSchema.options.join(", ")}`
|
|
20743
21061
|
);
|
|
20744
21062
|
return 2;
|
|
20745
21063
|
}
|
|
@@ -20781,6 +21099,37 @@ async function runQueryVerb(cmd, parsed) {
|
|
|
20781
21099
|
return exitCodeForError(err);
|
|
20782
21100
|
}
|
|
20783
21101
|
}
|
|
21102
|
+
async function runMonitorVerb(parsed) {
|
|
21103
|
+
const requestedProject = resolveProjectFlag(parsed);
|
|
21104
|
+
const baseUrl = await resolveDaemonUrl(requestedProject);
|
|
21105
|
+
const token = resolveAuthToken();
|
|
21106
|
+
const client = createHttpClient(baseUrl, token);
|
|
21107
|
+
let project;
|
|
21108
|
+
try {
|
|
21109
|
+
project = await resolveProjectForVerb(client, parsed);
|
|
21110
|
+
} catch (err) {
|
|
21111
|
+
if (err instanceof ProjectResolutionError) {
|
|
21112
|
+
console.error(`neat monitor: ${err.message}`);
|
|
21113
|
+
}
|
|
21114
|
+
return 0;
|
|
21115
|
+
}
|
|
21116
|
+
const controller = new AbortController();
|
|
21117
|
+
const onSignal = () => controller.abort();
|
|
21118
|
+
process.once("SIGINT", onSignal);
|
|
21119
|
+
process.once("SIGTERM", onSignal);
|
|
21120
|
+
try {
|
|
21121
|
+
return await runMonitor({
|
|
21122
|
+
baseUrl,
|
|
21123
|
+
project,
|
|
21124
|
+
json: parsed.json,
|
|
21125
|
+
authToken: token,
|
|
21126
|
+
signal: controller.signal
|
|
21127
|
+
});
|
|
21128
|
+
} finally {
|
|
21129
|
+
process.off("SIGINT", onSignal);
|
|
21130
|
+
process.off("SIGTERM", onSignal);
|
|
21131
|
+
}
|
|
21132
|
+
}
|
|
20784
21133
|
var entry = process.argv[1] ?? "";
|
|
20785
21134
|
if (/[\\/](?:cli\.(?:cjs|js)|cli|neat|neat\.is)$/.test(entry)) {
|
|
20786
21135
|
main().catch((err) => {
|
|
@@ -20802,6 +21151,7 @@ if (/[\\/](?:cli\.(?:cjs|js)|cli|neat|neat\.is)$/.test(entry)) {
|
|
|
20802
21151
|
resolveDaemonUrl,
|
|
20803
21152
|
resolveProjectForVerb,
|
|
20804
21153
|
runInit,
|
|
21154
|
+
runMonitorVerb,
|
|
20805
21155
|
runQueryVerb,
|
|
20806
21156
|
runSkill,
|
|
20807
21157
|
usage
|