@neat.is/core 0.3.4 → 0.3.5

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/neatd.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startDaemon
4
- } from "./chunk-T3A2GK3X.js";
4
+ } from "./chunk-KCEZSFU2.js";
5
5
  import {
6
6
  listProjects,
7
7
  registryPath
8
- } from "./chunk-33ZZ2ZID.js";
8
+ } from "./chunk-BUB3ASD5.js";
9
9
  import {
10
10
  __require
11
11
  } from "./chunk-4ASCXBZF.js";
package/dist/server.cjs CHANGED
@@ -716,11 +716,16 @@ init_cjs_shims();
716
716
  var import_types = require("@neat.is/types");
717
717
  var ROOT_CAUSE_MAX_DEPTH = 5;
718
718
  var BLAST_RADIUS_DEFAULT_DEPTH = 10;
719
+ function isFrontierNode(graph, nodeId) {
720
+ if (!graph.hasNode(nodeId)) return false;
721
+ const attrs = graph.getNodeAttributes(nodeId);
722
+ return attrs.type === import_types.NodeType.FrontierNode;
723
+ }
719
724
  function bestEdgeBySource(graph, edgeIds) {
720
725
  const best = /* @__PURE__ */ new Map();
721
726
  for (const id of edgeIds) {
722
727
  const e = graph.getEdgeAttributes(id);
723
- if (e.provenance === import_types.Provenance.FRONTIER) continue;
728
+ if (isFrontierNode(graph, e.source)) continue;
724
729
  const cur = best.get(e.source);
725
730
  if (!cur || import_types.PROV_RANK[e.provenance] > import_types.PROV_RANK[cur.provenance]) {
726
731
  best.set(e.source, e);
@@ -732,7 +737,7 @@ function bestEdgeByTarget(graph, edgeIds) {
732
737
  const best = /* @__PURE__ */ new Map();
733
738
  for (const id of edgeIds) {
734
739
  const e = graph.getEdgeAttributes(id);
735
- if (e.provenance === import_types.Provenance.FRONTIER) continue;
740
+ if (isFrontierNode(graph, e.target)) continue;
736
741
  const cur = best.get(e.target);
737
742
  if (!cur || import_types.PROV_RANK[e.provenance] > import_types.PROV_RANK[cur.provenance]) {
738
743
  best.set(e.target, e);
@@ -744,8 +749,7 @@ var PROVENANCE_CEILING = {
744
749
  OBSERVED: 1,
745
750
  INFERRED: 0.7,
746
751
  EXTRACTED: 0.5,
747
- STALE: 0.3,
748
- FRONTIER: 0.3
752
+ STALE: 0.3
749
753
  };
750
754
  function volumeWeight(spanCount) {
751
755
  if (!spanCount || spanCount <= 0) return 0.5;
@@ -1014,9 +1018,6 @@ function bucketEdges(graph) {
1014
1018
  case import_types2.Provenance.INFERRED:
1015
1019
  cur.inferred = e;
1016
1020
  break;
1017
- case import_types2.Provenance.FRONTIER:
1018
- cur.frontier = e;
1019
- break;
1020
1021
  default:
1021
1022
  if (e.provenance === import_types2.Provenance.STALE) cur.stale = e;
1022
1023
  }
@@ -1285,8 +1286,8 @@ var evaluateStructural = ({
1285
1286
  for (const edgeId of graph.outboundEdges(id)) {
1286
1287
  const e = graph.getEdgeAttributes(edgeId);
1287
1288
  if (e.type !== rule.edgeType) continue;
1288
- if (e.provenance === import_types3.Provenance.FRONTIER) continue;
1289
1289
  const target = graph.getNodeAttributes(e.target);
1290
+ if (target.type === import_types3.NodeType.FrontierNode) continue;
1290
1291
  if (target.type === rule.toNodeType) {
1291
1292
  satisfied = true;
1292
1293
  break;
@@ -1405,8 +1406,8 @@ var evaluateCompatibility = ({
1405
1406
  for (const edgeId of graph.outboundEdges(svcId)) {
1406
1407
  const e = graph.getEdgeAttributes(edgeId);
1407
1408
  if (e.type !== import_types3.EdgeType.CONNECTS_TO) continue;
1408
- if (e.provenance === import_types3.Provenance.FRONTIER) continue;
1409
1409
  const dbAttrs = graph.getNodeAttributes(e.target);
1410
+ if (dbAttrs.type === import_types3.NodeType.FrontierNode) continue;
1410
1411
  if (dbAttrs.type !== import_types3.NodeType.DatabaseNode) continue;
1411
1412
  const db = dbAttrs;
1412
1413
  for (const pair of compatPairs()) {
@@ -1732,31 +1733,6 @@ function ensureFrontierNode(graph, host, ts) {
1732
1733
  graph.addNode(id, node);
1733
1734
  return id;
1734
1735
  }
1735
- function upsertFrontierEdge(graph, type, source, target, ts) {
1736
- const id = (0, import_types4.frontierEdgeId)(source, target, type);
1737
- if (graph.hasEdge(id)) {
1738
- const existing = graph.getEdgeAttributes(id);
1739
- const updated = {
1740
- ...existing,
1741
- provenance: import_types4.Provenance.FRONTIER,
1742
- lastObserved: ts,
1743
- callCount: (existing.callCount ?? 0) + 1
1744
- };
1745
- graph.replaceEdgeAttributes(id, updated);
1746
- return;
1747
- }
1748
- const edge = {
1749
- id,
1750
- source,
1751
- target,
1752
- type,
1753
- provenance: import_types4.Provenance.FRONTIER,
1754
- confidence: 1,
1755
- lastObserved: ts,
1756
- callCount: 1
1757
- };
1758
- graph.addEdgeWithKey(id, source, target, edge);
1759
- }
1760
1736
  function upsertObservedEdge(graph, type, source, target, ts, isError = false) {
1761
1737
  if (!graph.hasNode(source) || !graph.hasNode(target)) return null;
1762
1738
  const id = makeObservedEdgeId(type, source, target);
@@ -1842,6 +1818,14 @@ async function appendErrorEvent(ctx, ev) {
1842
1818
  await import_node_fs3.promises.mkdir(import_node_path3.default.dirname(ctx.errorsPath), { recursive: true });
1843
1819
  await import_node_fs3.promises.appendFile(ctx.errorsPath, JSON.stringify(ev) + "\n", "utf8");
1844
1820
  }
1821
+ function sanitizeAttributes(attrs) {
1822
+ const out = {};
1823
+ for (const [k, v] of Object.entries(attrs)) {
1824
+ if (typeof v === "bigint") out[k] = v.toString();
1825
+ else out[k] = v;
1826
+ }
1827
+ return out;
1828
+ }
1845
1829
  async function handleSpan(ctx, span) {
1846
1830
  const ts = span.startTimeIso ?? nowIso(ctx);
1847
1831
  const nowMs = ctx.now ? ctx.now() : Date.now();
@@ -1881,11 +1865,16 @@ async function handleSpan(ctx, span) {
1881
1865
  affectedNode = targetId;
1882
1866
  resolvedViaAddress = true;
1883
1867
  } else if (!targetId) {
1884
- const frontierId2 = ensureFrontierNode(ctx.graph, host, ts);
1885
- if (ctx.graph.hasNode(sourceId)) {
1886
- upsertFrontierEdge(ctx.graph, import_types4.EdgeType.CALLS, sourceId, frontierId2, ts);
1887
- }
1888
- affectedNode = frontierId2;
1868
+ const frontierNodeId = ensureFrontierNode(ctx.graph, host, ts);
1869
+ upsertObservedEdge(
1870
+ ctx.graph,
1871
+ import_types4.EdgeType.CALLS,
1872
+ sourceId,
1873
+ frontierNodeId,
1874
+ ts,
1875
+ isError
1876
+ );
1877
+ affectedNode = frontierNodeId;
1889
1878
  resolvedViaAddress = true;
1890
1879
  }
1891
1880
  }
@@ -1907,15 +1896,17 @@ async function handleSpan(ctx, span) {
1907
1896
  if (span.statusCode === 2) {
1908
1897
  stitchTrace(ctx.graph, sourceId, ts);
1909
1898
  if (ctx.writeErrorEventInline !== false) {
1899
+ const attrs = sanitizeAttributes(span.attributes);
1910
1900
  const ev = {
1911
1901
  id: `${span.traceId}:${span.spanId}`,
1912
1902
  timestamp: ts,
1913
1903
  service: span.service,
1914
1904
  traceId: span.traceId,
1915
1905
  spanId: span.spanId,
1916
- errorMessage: span.exception?.message ?? span.errorMessage ?? span.name ?? "unknown error",
1906
+ errorMessage: span.exception?.message ?? span.name ?? "unknown error",
1917
1907
  ...span.exception?.type ? { exceptionType: span.exception.type } : {},
1918
1908
  ...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
1909
+ ...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
1919
1910
  affectedNode
1920
1911
  };
1921
1912
  await appendErrorEvent(ctx, ev);
@@ -1971,8 +1962,7 @@ function rewireFrontierEdges(graph, frontierId2, serviceId3) {
1971
1962
  }
1972
1963
  function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
1973
1964
  graph.dropEdge(oldEdgeId);
1974
- const promotedProvenance = edge.provenance === import_types4.Provenance.FRONTIER ? import_types4.Provenance.OBSERVED : edge.provenance;
1975
- const newId = promotedProvenance === import_types4.Provenance.OBSERVED ? (0, import_types4.observedEdgeId)(newSource, newTarget, edge.type) : promotedProvenance === import_types4.Provenance.INFERRED ? (0, import_types4.inferredEdgeId)(newSource, newTarget, edge.type) : promotedProvenance === import_types4.Provenance.EXTRACTED ? (0, import_types4.extractedEdgeId)(newSource, newTarget, edge.type) : (0, import_types4.frontierEdgeId)(newSource, newTarget, edge.type);
1965
+ const newId = edge.provenance === import_types4.Provenance.OBSERVED ? (0, import_types4.observedEdgeId)(newSource, newTarget, edge.type) : edge.provenance === import_types4.Provenance.INFERRED ? (0, import_types4.inferredEdgeId)(newSource, newTarget, edge.type) : (0, import_types4.extractedEdgeId)(newSource, newTarget, edge.type);
1976
1966
  if (graph.hasEdge(newId)) {
1977
1967
  const existing = graph.getEdgeAttributes(newId);
1978
1968
  const merged = {
@@ -1987,8 +1977,7 @@ function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
1987
1977
  ...edge,
1988
1978
  id: newId,
1989
1979
  source: newSource,
1990
- target: newTarget,
1991
- provenance: promotedProvenance
1980
+ target: newTarget
1992
1981
  };
1993
1982
  graph.addEdgeWithKey(newId, newSource, newTarget, rebuilt);
1994
1983
  }
@@ -4937,7 +4926,8 @@ async function buildApi(opts) {
4937
4926
  init_cjs_shims();
4938
4927
  var import_node_fs20 = require("fs");
4939
4928
  var import_node_path33 = __toESM(require("path"), 1);
4940
- var SCHEMA_VERSION = 2;
4929
+ var import_types22 = require("@neat.is/types");
4930
+ var SCHEMA_VERSION = 3;
4941
4931
  function migrateV1ToV2(payload) {
4942
4932
  const nodes = payload.graph.nodes;
4943
4933
  if (Array.isArray(nodes)) {
@@ -4949,6 +4939,25 @@ function migrateV1ToV2(payload) {
4949
4939
  }
4950
4940
  return { ...payload, schemaVersion: 2 };
4951
4941
  }
4942
+ function migrateV2ToV3(payload) {
4943
+ const edges = payload.graph.edges;
4944
+ if (Array.isArray(edges)) {
4945
+ for (const edge of edges) {
4946
+ const attrs = edge.attributes;
4947
+ if (!attrs || attrs.provenance !== "FRONTIER") continue;
4948
+ attrs.provenance = import_types22.Provenance.OBSERVED;
4949
+ const type = typeof attrs.type === "string" ? attrs.type : void 0;
4950
+ const source = typeof attrs.source === "string" ? attrs.source : void 0;
4951
+ const target = typeof attrs.target === "string" ? attrs.target : void 0;
4952
+ if (type && source && target) {
4953
+ const newId = (0, import_types22.observedEdgeId)(source, target, type);
4954
+ attrs.id = newId;
4955
+ if (edge.key) edge.key = newId;
4956
+ }
4957
+ }
4958
+ }
4959
+ return { ...payload, schemaVersion: 3 };
4960
+ }
4952
4961
  async function ensureDir(filePath) {
4953
4962
  await import_node_fs20.promises.mkdir(import_node_path33.default.dirname(filePath), { recursive: true });
4954
4963
  }
@@ -4975,6 +4984,9 @@ async function loadGraphFromDisk(graph, outPath) {
4975
4984
  if (payload.schemaVersion === 1) {
4976
4985
  payload = migrateV1ToV2(payload);
4977
4986
  }
4987
+ if (payload.schemaVersion === 2) {
4988
+ payload = migrateV2ToV3(payload);
4989
+ }
4978
4990
  if (payload.schemaVersion !== SCHEMA_VERSION) {
4979
4991
  throw new Error(
4980
4992
  `persist: unsupported snapshot schemaVersion ${payload.schemaVersion} (expected ${SCHEMA_VERSION})`