@neat.is/core 0.9.21-dev.20260924 → 0.9.21
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/{chunk-NFJ4W5T6.js → chunk-J3VVEB45.js} +200 -50
- package/dist/chunk-J3VVEB45.js.map +1 -0
- package/dist/{chunk-SK2FEJKB.js → chunk-KVJQQUUY.js} +186 -40
- package/dist/chunk-KVJQQUUY.js.map +1 -0
- package/dist/cli.cjs +494 -345
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +470 -177
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +482 -189
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +225 -78
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-NFJ4W5T6.js.map +0 -1
- package/dist/chunk-SK2FEJKB.js.map +0 -1
package/dist/server.cjs
CHANGED
|
@@ -787,7 +787,7 @@ function getGraph(project = DEFAULT_PROJECT) {
|
|
|
787
787
|
init_cjs_shims();
|
|
788
788
|
var import_fastify2 = __toESM(require("fastify"), 1);
|
|
789
789
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
790
|
-
var
|
|
790
|
+
var import_types101 = require("@neat.is/types");
|
|
791
791
|
|
|
792
792
|
// src/extend/index.ts
|
|
793
793
|
init_cjs_shims();
|
|
@@ -17397,7 +17397,7 @@ var INTENT_RULES = [
|
|
|
17397
17397
|
},
|
|
17398
17398
|
{
|
|
17399
17399
|
intent: "blast-radius",
|
|
17400
|
-
test: /\b(blast|break[\s-]?if|breaks[\s-]?if|impact|downstream|dependents?|redeploy|who\s+(?:uses|calls|depends)|what\s+depends\s+on|affect(?:s|ed)?)\b/
|
|
17400
|
+
test: /\b(blast|break[\s-]?if|breaks[\s-]?if|impact|downstream|dependents?|redeploy|who\s+(?:uses|calls|depends(?:\s+on)?)|what\s+depends\s+on|consumers?\s+of|callers?\s+of|affect(?:s|ed)?)\b/
|
|
17401
17401
|
},
|
|
17402
17402
|
{
|
|
17403
17403
|
intent: "divergence",
|
|
@@ -17409,11 +17409,11 @@ var INTENT_RULES = [
|
|
|
17409
17409
|
},
|
|
17410
17410
|
{
|
|
17411
17411
|
intent: "observed",
|
|
17412
|
-
test: /\b(at\s+runtime|in\s+prod(?:uction)?|actually
|
|
17412
|
+
test: /\b(at\s+runtime|in\s+prod(?:uction)?|actually|really\s+call\w*|observed|runtime\s+traffic|slow|latency|p95|timing)\b/
|
|
17413
17413
|
},
|
|
17414
17414
|
{
|
|
17415
17415
|
intent: "dependencies",
|
|
17416
|
-
test: /\b(depend\w*|calls?|uses?|imports?|relies\s+on|needs
|
|
17416
|
+
test: /\b(depend\w*|calls?|uses?|imports?|relies\s+on|needs?|talks?\s+to|connects?\s+to|hits?|reads?\s+from|writes?\s+to)\b/
|
|
17417
17417
|
}
|
|
17418
17418
|
];
|
|
17419
17419
|
function classifyIntent(question) {
|
|
@@ -17580,7 +17580,25 @@ var INTENT_WORDS = /* @__PURE__ */ new Set([
|
|
|
17580
17580
|
"rely",
|
|
17581
17581
|
"needs",
|
|
17582
17582
|
"need",
|
|
17583
|
-
"sync"
|
|
17583
|
+
"sync",
|
|
17584
|
+
"talk",
|
|
17585
|
+
"talks",
|
|
17586
|
+
"connect",
|
|
17587
|
+
"connects",
|
|
17588
|
+
"hit",
|
|
17589
|
+
"hits",
|
|
17590
|
+
"read",
|
|
17591
|
+
"reads",
|
|
17592
|
+
"write",
|
|
17593
|
+
"writes",
|
|
17594
|
+
"consumer",
|
|
17595
|
+
"consumers",
|
|
17596
|
+
"caller",
|
|
17597
|
+
"callers",
|
|
17598
|
+
"slow",
|
|
17599
|
+
"latency",
|
|
17600
|
+
"p95",
|
|
17601
|
+
"timing"
|
|
17584
17602
|
]);
|
|
17585
17603
|
function tokens(input) {
|
|
17586
17604
|
const spaced = input.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
|
|
@@ -17604,6 +17622,13 @@ function idBody(id) {
|
|
|
17604
17622
|
const colon = id.indexOf(":");
|
|
17605
17623
|
return colon >= 0 ? id.slice(colon + 1) : id;
|
|
17606
17624
|
}
|
|
17625
|
+
var TYPE_NOUNS = [
|
|
17626
|
+
{ nouns: ["database", "db", "table"], type: import_types61.NodeType.DatabaseNode },
|
|
17627
|
+
{ nouns: ["service", "api", "backend"], type: import_types61.NodeType.ServiceNode },
|
|
17628
|
+
{ nouns: ["route", "endpoint"], type: import_types61.NodeType.RouteNode },
|
|
17629
|
+
{ nouns: ["file"], type: import_types61.NodeType.FileNode },
|
|
17630
|
+
{ nouns: ["config"], type: import_types61.NodeType.ConfigNode }
|
|
17631
|
+
];
|
|
17607
17632
|
var EMBED_MIN_SCORE = 0.35;
|
|
17608
17633
|
async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
17609
17634
|
const qTokens = queryTokens(question);
|
|
@@ -17611,6 +17636,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
|
17611
17636
|
const best = /* @__PURE__ */ new Map();
|
|
17612
17637
|
const consider = (cand) => {
|
|
17613
17638
|
const cur = best.get(cand.nodeId);
|
|
17639
|
+
if (cur?.via === "id" && cand.via === "embedding") return;
|
|
17614
17640
|
if (!cur || cand.score > cur.score) best.set(cand.nodeId, cand);
|
|
17615
17641
|
};
|
|
17616
17642
|
graph.forEachNode((id, attrs) => {
|
|
@@ -17620,12 +17646,12 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
|
17620
17646
|
const body = idBody(id);
|
|
17621
17647
|
const labelTokens = /* @__PURE__ */ new Set([...tokens(body), ...tokens(name)]);
|
|
17622
17648
|
if (labelTokens.size === 0) return;
|
|
17623
|
-
let
|
|
17624
|
-
for (const t of qTokens) if (labelTokens.has(t))
|
|
17649
|
+
let matched2 = 0;
|
|
17650
|
+
for (const t of qTokens) if (labelTokens.has(t)) matched2 += 1;
|
|
17625
17651
|
const named = body.length >= 2 && normalized.includes(body.toLowerCase()) || name.length >= 2 && normalized.includes(name.toLowerCase());
|
|
17626
|
-
if (
|
|
17627
|
-
const coverage = qTokens.length > 0 ?
|
|
17628
|
-
const via = named ? "id" :
|
|
17652
|
+
if (matched2 === 0 && !named) return;
|
|
17653
|
+
const coverage = qTokens.length > 0 ? matched2 / qTokens.length : 0;
|
|
17654
|
+
const via = named ? "id" : matched2 > 0 && tokens(name).some((t) => qTokens.includes(t)) ? "label" : "token";
|
|
17629
17655
|
const score = named ? Math.max(0.9, coverage) : Math.min(0.85, 0.3 + 0.7 * coverage);
|
|
17630
17656
|
consider({ nodeId: id, label: name, via, score: Math.min(1, score) });
|
|
17631
17657
|
});
|
|
@@ -17635,6 +17661,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
|
17635
17661
|
if (res.provider !== "substring") {
|
|
17636
17662
|
for (const m of res.matches) {
|
|
17637
17663
|
if (m.node.type === import_types61.NodeType.FrontierNode) continue;
|
|
17664
|
+
if (!graph.hasNode(m.node.id)) continue;
|
|
17638
17665
|
const already = best.get(m.node.id);
|
|
17639
17666
|
if (!already && m.score < EMBED_MIN_SCORE) continue;
|
|
17640
17667
|
consider({
|
|
@@ -17648,10 +17675,31 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
|
17648
17675
|
} catch {
|
|
17649
17676
|
}
|
|
17650
17677
|
}
|
|
17651
|
-
|
|
17652
|
-
|
|
17653
|
-
|
|
17678
|
+
if (best.size === 0) {
|
|
17679
|
+
const words = new Set(tokens(question));
|
|
17680
|
+
const kind = TYPE_NOUNS.find((entry) => entry.nouns.some((noun) => words.has(noun)));
|
|
17681
|
+
if (kind) {
|
|
17682
|
+
const ids = graph.filterNodes((_id, attrs) => attrs.type === kind.type).sort();
|
|
17683
|
+
if (ids.length > 1) {
|
|
17684
|
+
return { matched: [], ambiguousType: { noun: kind.nouns.find((noun) => words.has(noun)), ids } };
|
|
17685
|
+
}
|
|
17686
|
+
if (ids.length === 1) {
|
|
17687
|
+
const id = ids[0];
|
|
17688
|
+
return { matched: [{ nodeId: id, label: nodeName(graph.getNodeAttributes(id)), via: "type", score: 0.6 }].slice(0, maxNodes) };
|
|
17689
|
+
}
|
|
17690
|
+
return { matched: [] };
|
|
17691
|
+
}
|
|
17692
|
+
}
|
|
17693
|
+
const viaRank = { id: 4, label: 3, token: 2, type: 1, embedding: 0 };
|
|
17694
|
+
const ranked = [...best.values()].sort(
|
|
17695
|
+
(a, b) => Number(b.via === "id") - Number(a.via === "id") || b.score - a.score || viaRank[b.via] - viaRank[a.via] || a.nodeId.localeCompare(b.nodeId)
|
|
17696
|
+
);
|
|
17697
|
+
const primary = ranked[0];
|
|
17698
|
+
const primaryType = primary && graph.getNodeAttributes(primary.nodeId).type;
|
|
17699
|
+
const matched = ranked.filter(
|
|
17700
|
+
(candidate) => !primary || primary.via !== "id" || primary.score < 0.85 || candidate === primary || graph.getNodeAttributes(candidate.nodeId).type === primaryType || candidate.via !== "embedding" && candidate.score >= primary.score - 0.2
|
|
17654
17701
|
).slice(0, maxNodes).map((s) => ({ nodeId: s.nodeId, label: s.label, via: s.via, score: Number(s.score.toFixed(3)) }));
|
|
17702
|
+
return { matched };
|
|
17655
17703
|
}
|
|
17656
17704
|
function incidentsForNode(nodeId, incidents) {
|
|
17657
17705
|
if (!incidents || incidents.length === 0) return [];
|
|
@@ -17743,6 +17791,23 @@ function buildBlastSection(graph, node) {
|
|
|
17743
17791
|
facts
|
|
17744
17792
|
};
|
|
17745
17793
|
}
|
|
17794
|
+
function buildDatabaseCallersSection(graph, node) {
|
|
17795
|
+
const callers = getBlastRadius(graph, node).affectedNodes.filter((item) => {
|
|
17796
|
+
if (graph.getNodeAttributes(item.nodeId).type !== import_types61.NodeType.ServiceNode) return false;
|
|
17797
|
+
return item.path.slice(1, -1).every((id) => {
|
|
17798
|
+
const type = graph.getNodeAttributes(id).type;
|
|
17799
|
+
return type === import_types61.NodeType.FileNode || type === import_types61.NodeType.SymbolNode;
|
|
17800
|
+
});
|
|
17801
|
+
});
|
|
17802
|
+
return {
|
|
17803
|
+
heading: `Services calling ${node} \u2014 ${callers.length}`,
|
|
17804
|
+
facts: callers.length > 0 ? callers.slice(0, MAX_FACTS_PER_SECTION).map((item) => ({
|
|
17805
|
+
text: `${item.nodeId} (distance ${item.distance})`,
|
|
17806
|
+
provenance: item.edgeProvenance,
|
|
17807
|
+
confidence: item.confidence
|
|
17808
|
+
})) : [{ text: `No inbound service callers found for ${node}.` }]
|
|
17809
|
+
};
|
|
17810
|
+
}
|
|
17746
17811
|
function buildIncidentsSection(node, incidents) {
|
|
17747
17812
|
const relevant = incidentsForNode(node, incidents);
|
|
17748
17813
|
if (relevant.length === 0) return null;
|
|
@@ -17769,6 +17834,29 @@ function divergenceLine(d) {
|
|
|
17769
17834
|
}
|
|
17770
17835
|
return `[${d.type}] ${d.source} \u2192 ${d.target} \u2014 ${d.reason}`;
|
|
17771
17836
|
}
|
|
17837
|
+
function runtimeEdgeState(graph) {
|
|
17838
|
+
let observed = false;
|
|
17839
|
+
let stale = false;
|
|
17840
|
+
graph.forEachEdge((_id, attrs) => {
|
|
17841
|
+
if (attrs.provenance === import_types61.Provenance.OBSERVED) observed = true;
|
|
17842
|
+
if (attrs.provenance === import_types61.Provenance.STALE) stale = true;
|
|
17843
|
+
});
|
|
17844
|
+
return { observed, stale };
|
|
17845
|
+
}
|
|
17846
|
+
function pendingRuntimeMessage(graph, divergences) {
|
|
17847
|
+
const count = divergences.filter((d) => d.type === "missing-observed").length;
|
|
17848
|
+
if (count === 0) return void 0;
|
|
17849
|
+
const { observed, stale } = runtimeEdgeState(graph);
|
|
17850
|
+
if (observed) return void 0;
|
|
17851
|
+
const prefix = stale ? "No current runtime observations \u2014 earlier runtime evidence is stale" : "No runtime observed yet";
|
|
17852
|
+
return `${prefix} \u2014 ${count} declared dependenc${count === 1 ? "y is" : "ies are"} waiting to be confirmed. Send traces (or connect a provider) and ask again.`;
|
|
17853
|
+
}
|
|
17854
|
+
function noDivergenceMessage(graph) {
|
|
17855
|
+
if (graph.order === 0) return "Graph is empty \u2014 no declared or observed dependencies to compare.";
|
|
17856
|
+
const { observed, stale } = runtimeEdgeState(graph);
|
|
17857
|
+
if (!observed) return stale ? "No current runtime dependency observations to compare \u2014 earlier runtime evidence is stale." : "No runtime dependency observations to compare with declared code.";
|
|
17858
|
+
return "None \u2014 declared code and observed runtime agree across the graph.";
|
|
17859
|
+
}
|
|
17772
17860
|
function buildDivergenceSection(graph, node, incidents) {
|
|
17773
17861
|
const result = computeDivergences(graph, { node, ...incidents ? { incidents } : {} });
|
|
17774
17862
|
if (result.totalAffected === 0) return null;
|
|
@@ -17785,19 +17873,28 @@ function buildDivergenceSection(graph, node, incidents) {
|
|
|
17785
17873
|
}
|
|
17786
17874
|
function buildGlobalDivergenceSection(graph, incidents) {
|
|
17787
17875
|
const result = computeDivergences(graph, incidents ? { incidents } : {});
|
|
17876
|
+
const pending = pendingRuntimeMessage(graph, result.divergences);
|
|
17877
|
+
const visible = pending ? result.divergences.filter((d) => d.type !== "missing-observed") : result.divergences;
|
|
17878
|
+
if (visible.length === 0 && pending) {
|
|
17879
|
+
return {
|
|
17880
|
+
heading: "Divergences (EXTRACTED vs OBSERVED)",
|
|
17881
|
+
facts: [{ text: pending }]
|
|
17882
|
+
};
|
|
17883
|
+
}
|
|
17788
17884
|
if (result.totalAffected === 0) {
|
|
17789
17885
|
return {
|
|
17790
17886
|
heading: "Divergences (EXTRACTED vs OBSERVED)",
|
|
17791
|
-
facts: [{ text:
|
|
17887
|
+
facts: [{ text: noDivergenceMessage(graph) }]
|
|
17792
17888
|
};
|
|
17793
17889
|
}
|
|
17794
|
-
const facts =
|
|
17890
|
+
const facts = visible.slice(0, MAX_FACTS_PER_SECTION).map((d) => ({
|
|
17795
17891
|
text: divergenceLine(d),
|
|
17796
17892
|
confidence: d.confidence
|
|
17797
17893
|
// Composite by construction (EXTRACTED vs OBSERVED), so no single provenance.
|
|
17798
17894
|
}));
|
|
17895
|
+
if (pending && facts.length < MAX_FACTS_PER_SECTION) facts.push({ text: pending });
|
|
17799
17896
|
return {
|
|
17800
|
-
heading: `Divergences (EXTRACTED vs OBSERVED) \u2014 ${
|
|
17897
|
+
heading: `Divergences (EXTRACTED vs OBSERVED) \u2014 ${visible.length}`,
|
|
17801
17898
|
facts
|
|
17802
17899
|
};
|
|
17803
17900
|
}
|
|
@@ -17883,13 +17980,12 @@ function buildOverviewSections(graph, incidents) {
|
|
|
17883
17980
|
});
|
|
17884
17981
|
}
|
|
17885
17982
|
const div = computeDivergences(graph, incidents ? { incidents } : {});
|
|
17983
|
+
const pending = pendingRuntimeMessage(graph, div.divergences);
|
|
17984
|
+
const visibleCount = pending ? div.divergences.filter((d) => d.type !== "missing-observed").length : div.totalAffected;
|
|
17985
|
+
const divergenceText = visibleCount > 0 ? `${visibleCount} divergence${visibleCount === 1 ? "" : "s"} between declared code and observed runtime \u2014 ask "are there any divergences?" for the list.${pending ? ` ${pending}` : ""}` : pending ?? noDivergenceMessage(graph);
|
|
17886
17986
|
sections.push({
|
|
17887
17987
|
heading: "Divergences",
|
|
17888
|
-
facts: [
|
|
17889
|
-
{
|
|
17890
|
-
text: div.totalAffected === 0 ? "None \u2014 declared code and observed runtime agree across the graph." : `${div.totalAffected} divergence${div.totalAffected === 1 ? "" : "s"} between declared code and observed runtime \u2014 ask "are there any divergences?" for the list.`
|
|
17891
|
-
}
|
|
17892
|
-
]
|
|
17988
|
+
facts: [{ text: divergenceText }]
|
|
17893
17989
|
});
|
|
17894
17990
|
return sections;
|
|
17895
17991
|
}
|
|
@@ -17934,6 +18030,8 @@ function summarizeGlobal(intent, sections) {
|
|
|
17934
18030
|
const lead = sections[0];
|
|
17935
18031
|
switch (intent) {
|
|
17936
18032
|
case "divergence": {
|
|
18033
|
+
const pending = lead?.facts[0]?.text;
|
|
18034
|
+
if (pending?.startsWith("No runtime") || pending?.startsWith("No current runtime") || pending?.startsWith("Graph is empty")) return pending;
|
|
17937
18035
|
const none = lead?.facts[0]?.text.startsWith("None") ?? true;
|
|
17938
18036
|
return none ? "No divergences across the graph \u2014 declared code and observed runtime agree." : `${lead.heading} across the graph, highest-confidence first below.`;
|
|
17939
18037
|
}
|
|
@@ -17946,11 +18044,16 @@ function summarizeGlobal(intent, sections) {
|
|
|
17946
18044
|
return `System overview across the whole graph: ${sections.length} view${sections.length === 1 ? "" : "s"} below \u2014 shape (nodes/edges by provenance), busiest services, incidents, and divergences.`;
|
|
17947
18045
|
}
|
|
17948
18046
|
}
|
|
17949
|
-
function summarize(question, intent, matched, primary, sections, scope) {
|
|
18047
|
+
function summarize(question, intent, matched, primary, sections, scope, ambiguousType) {
|
|
17950
18048
|
if (scope === "global") {
|
|
17951
18049
|
return summarizeGlobal(intent, sections);
|
|
17952
18050
|
}
|
|
17953
18051
|
if (!primary) {
|
|
18052
|
+
if (ambiguousType) {
|
|
18053
|
+
const shown = ambiguousType.ids.slice(0, 10);
|
|
18054
|
+
const more = ambiguousType.ids.length - shown.length;
|
|
18055
|
+
return `"${ambiguousType.noun}" matches ${ambiguousType.ids.length} nodes. Name one by ID: ${shown.join(", ")}${more > 0 ? `, and ${more} more` : ""}.`;
|
|
18056
|
+
}
|
|
17954
18057
|
return `Nothing in "${question}" resolved to a node in the graph. Name a service, file, route, or table \u2014 e.g. \`ask "what does <service> depend on?"\`. For a graph-wide look, ask for an overview, divergences, or incidents.`;
|
|
17955
18058
|
}
|
|
17956
18059
|
const lead = sections[0];
|
|
@@ -17973,10 +18076,13 @@ function summarize(question, intent, matched, primary, sections, scope) {
|
|
|
17973
18076
|
core = lead ? `${lead.heading} of ${primary}.` : `${primary} has no dependents \u2014 nothing else would break if it failed.`;
|
|
17974
18077
|
break;
|
|
17975
18078
|
case "dependencies":
|
|
17976
|
-
core = lead ? `${primary}: ${lead.heading.toLowerCase()} listed below.` : `${primary} has no declared dependencies in the graph.`;
|
|
18079
|
+
core = lead?.heading.startsWith("Services calling") ? `${lead.heading}.` : lead ? `${primary}: ${lead.heading.toLowerCase()} listed below.` : `${primary} has no declared dependencies in the graph.`;
|
|
17977
18080
|
break;
|
|
17978
18081
|
case "observed":
|
|
17979
|
-
|
|
18082
|
+
{
|
|
18083
|
+
const observed = sections.find((s) => s.heading === "Runtime dependencies (OBSERVED)");
|
|
18084
|
+
core = observed ? `${primary} at runtime: ${observed.facts.length} OBSERVED fact${observed.facts.length === 1 ? "" : "s"}.` : `No runtime traffic OBSERVED for ${primary}.`;
|
|
18085
|
+
}
|
|
17980
18086
|
break;
|
|
17981
18087
|
case "incidents":
|
|
17982
18088
|
core = lead ? `${primary}: ${lead.heading.toLowerCase()}.` : `No incidents recorded against ${primary}.`;
|
|
@@ -17993,24 +18099,28 @@ async function askGraph(graph, question, opts = {}) {
|
|
|
17993
18099
|
const now = opts.now ?? Date.now();
|
|
17994
18100
|
const maxNodes = opts.maxNodes ?? DEFAULT_MAX_NODES;
|
|
17995
18101
|
const intent = classifyIntent(question);
|
|
17996
|
-
const
|
|
18102
|
+
const resolution = await resolveEntities(graph, question, opts.searchIndex, maxNodes);
|
|
18103
|
+
const matched = resolution.matched;
|
|
17997
18104
|
const primary = matched[0]?.nodeId;
|
|
17998
18105
|
const sections = [];
|
|
17999
18106
|
let scope;
|
|
18000
18107
|
if (primary) {
|
|
18001
18108
|
scope = "node";
|
|
18109
|
+
const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type === import_types61.NodeType.DatabaseNode && /\b(?:which|what)\s+services?\s+(?:talks?\s+to|connects?\s+to|uses?|hits?|calls?|reads?\s+from|writes?\s+to)\b/i.test(question);
|
|
18110
|
+
if (callersQuestion) sections.push(buildDatabaseCallersSection(graph, primary));
|
|
18002
18111
|
for (const kind of SECTION_ORDER[intent]) {
|
|
18112
|
+
if (callersQuestion && kind === "blast") continue;
|
|
18003
18113
|
const s = buildSection(kind, graph, primary, opts.incidents, now);
|
|
18004
18114
|
if (s && s.facts.length > 0) sections.push(s);
|
|
18005
18115
|
}
|
|
18006
18116
|
} else {
|
|
18007
|
-
const global = buildGlobalSections(intent, graph, opts.incidents);
|
|
18117
|
+
const global = resolution.ambiguousType ? null : buildGlobalSections(intent, graph, opts.incidents);
|
|
18008
18118
|
if (global) {
|
|
18009
18119
|
scope = "global";
|
|
18010
18120
|
for (const s of global) if (s.facts.length > 0) sections.push(s);
|
|
18011
18121
|
}
|
|
18012
18122
|
}
|
|
18013
|
-
const answer = summarize(question, intent, matched, primary, sections, scope);
|
|
18123
|
+
const answer = summarize(question, intent, matched, primary, sections, scope, resolution.ambiguousType);
|
|
18014
18124
|
const provSet = /* @__PURE__ */ new Set();
|
|
18015
18125
|
for (const s of sections) for (const f of s.facts) if (f.provenance) provSet.add(f.provenance);
|
|
18016
18126
|
const confidence = sections[0]?.facts[0]?.confidence;
|
|
@@ -19813,9 +19923,9 @@ var RESOURCE_TYPES = [
|
|
|
19813
19923
|
function isFirebaseResourceType(value) {
|
|
19814
19924
|
return RESOURCE_TYPES.includes(value);
|
|
19815
19925
|
}
|
|
19816
|
-
function buildEntriesFilter(sinceIso) {
|
|
19926
|
+
function buildEntriesFilter(sinceIso, resourceTypes = RESOURCE_TYPES) {
|
|
19817
19927
|
return [
|
|
19818
|
-
|
|
19928
|
+
`resource.type = (${resourceTypes.map((t) => `"${t}"`).join(" OR ")})`,
|
|
19819
19929
|
"httpRequest:*",
|
|
19820
19930
|
`timestamp >= "${sinceIso}"`
|
|
19821
19931
|
].join(" AND ");
|
|
@@ -19824,8 +19934,8 @@ var DEFAULT_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
|
|
|
19824
19934
|
var ENTRIES_LIST_URL = "https://logging.googleapis.com/v2/entries:list";
|
|
19825
19935
|
var PAGE_SIZE = 1e3;
|
|
19826
19936
|
var MAX_PAGES = 20;
|
|
19827
|
-
async function fetchHttpRequestLogEntries(creds, sinceIso) {
|
|
19828
|
-
const filter = buildEntriesFilter(sinceIso);
|
|
19937
|
+
async function fetchHttpRequestLogEntries(creds, sinceIso, resourceTypes) {
|
|
19938
|
+
const filter = buildEntriesFilter(sinceIso, resourceTypes);
|
|
19829
19939
|
const out = [];
|
|
19830
19940
|
let pageToken;
|
|
19831
19941
|
for (let page = 0; page < MAX_PAGES; page++) {
|
|
@@ -19940,7 +20050,38 @@ function mapLogEntriesToSignals(entries) {
|
|
|
19940
20050
|
|
|
19941
20051
|
// src/connectors/firebase/resolve.ts
|
|
19942
20052
|
init_cjs_shims();
|
|
20053
|
+
var import_types72 = require("@neat.is/types");
|
|
20054
|
+
|
|
20055
|
+
// src/connectors/infer-service.ts
|
|
20056
|
+
init_cjs_shims();
|
|
19943
20057
|
var import_types71 = require("@neat.is/types");
|
|
20058
|
+
function normalizeName(name) {
|
|
20059
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
20060
|
+
}
|
|
20061
|
+
function inferServiceName(graph, resourceName, method, path77) {
|
|
20062
|
+
const wantedMethod = method.toUpperCase();
|
|
20063
|
+
const wantedPath = normalizePathTemplate(path77);
|
|
20064
|
+
const services = [];
|
|
20065
|
+
const owners = /* @__PURE__ */ new Set();
|
|
20066
|
+
graph.forEachNode((_id, attrs) => {
|
|
20067
|
+
const node = attrs;
|
|
20068
|
+
if (node.type === import_types71.NodeType.ServiceNode && typeof node.name === "string") {
|
|
20069
|
+
services.push(node.name);
|
|
20070
|
+
return;
|
|
20071
|
+
}
|
|
20072
|
+
if (node.type !== import_types71.NodeType.RouteNode) return;
|
|
20073
|
+
const route = attrs;
|
|
20074
|
+
if (!route.pathTemplate || normalizePathTemplate(route.pathTemplate) !== wantedPath) return;
|
|
20075
|
+
const routeMethod = route.method.toUpperCase();
|
|
20076
|
+
if (routeMethod === "ALL" || routeMethod === wantedMethod) owners.add(route.service);
|
|
20077
|
+
});
|
|
20078
|
+
const wanted = normalizeName(resourceName);
|
|
20079
|
+
const byName = services.find((s) => normalizeName(s) === wanted);
|
|
20080
|
+
if (byName) return byName;
|
|
20081
|
+
return owners.size === 1 ? [...owners][0] : null;
|
|
20082
|
+
}
|
|
20083
|
+
|
|
20084
|
+
// src/connectors/firebase/resolve.ts
|
|
19944
20085
|
function neatServiceNameFor(resourceType, resourceName, serviceMap) {
|
|
19945
20086
|
switch (resourceType) {
|
|
19946
20087
|
case "cloud_function":
|
|
@@ -19955,7 +20096,7 @@ function routeEntriesFor(graph, serviceName) {
|
|
|
19955
20096
|
const entries = [];
|
|
19956
20097
|
graph.forEachNode((_id, attrs) => {
|
|
19957
20098
|
const node = attrs;
|
|
19958
|
-
if (node.type !==
|
|
20099
|
+
if (node.type !== import_types72.NodeType.RouteNode) return;
|
|
19959
20100
|
const route = attrs;
|
|
19960
20101
|
if (route.service !== serviceName) return;
|
|
19961
20102
|
entries.push({
|
|
@@ -19979,32 +20120,38 @@ function createFirebaseResolveTarget(graph, serviceMap) {
|
|
|
19979
20120
|
}
|
|
19980
20121
|
const identity = parseFirebaseTargetName(signal.targetName);
|
|
19981
20122
|
if (!identity) return null;
|
|
19982
|
-
const serviceName = neatServiceNameFor(resourceType, identity.resourceName, serviceMap);
|
|
19983
|
-
if (!serviceName) return null;
|
|
19984
20123
|
const normalizedPath = normalizePathTemplate(identity.path);
|
|
20124
|
+
const serviceName = neatServiceNameFor(resourceType, identity.resourceName, serviceMap) ?? (serviceMap.inferServices ? inferServiceName(graph, identity.resourceName, identity.method, identity.path) : null);
|
|
20125
|
+
if (!serviceName) return null;
|
|
19985
20126
|
const match = findRoute2(routeEntriesFor(graph, serviceName), identity.method, normalizedPath);
|
|
19986
20127
|
if (!match) return null;
|
|
19987
20128
|
return {
|
|
19988
20129
|
targetNodeId: match.routeNodeId,
|
|
19989
20130
|
serviceName,
|
|
19990
|
-
edgeType:
|
|
20131
|
+
edgeType: import_types72.EdgeType.CALLS
|
|
19991
20132
|
};
|
|
19992
20133
|
};
|
|
19993
20134
|
}
|
|
19994
20135
|
|
|
19995
20136
|
// src/connectors/firebase/index.ts
|
|
19996
20137
|
var FirebaseConnector = class {
|
|
20138
|
+
constructor(opts = {}) {
|
|
20139
|
+
this.opts = opts;
|
|
20140
|
+
}
|
|
20141
|
+
opts;
|
|
19997
20142
|
provider = "firebase";
|
|
19998
20143
|
async poll(ctx) {
|
|
19999
20144
|
const creds = readFirebaseCredentials(ctx.credentials);
|
|
20000
20145
|
const sinceIso = ctx.since ?? new Date(Date.now() - DEFAULT_LOOKBACK_MS).toISOString();
|
|
20001
|
-
const entries = await fetchHttpRequestLogEntries(creds, sinceIso);
|
|
20146
|
+
const entries = await fetchHttpRequestLogEntries(creds, sinceIso, this.opts.resourceTypes);
|
|
20002
20147
|
return mapLogEntriesToSignals(entries);
|
|
20003
20148
|
}
|
|
20004
20149
|
};
|
|
20005
20150
|
function createFirebaseConnector(graph, serviceMap) {
|
|
20006
20151
|
return {
|
|
20007
|
-
connector: new FirebaseConnector(
|
|
20152
|
+
connector: new FirebaseConnector(
|
|
20153
|
+
serviceMap.excludeCloudRun ? { resourceTypes: ["cloud_function", "firebase_domain"] } : {}
|
|
20154
|
+
),
|
|
20008
20155
|
resolveTarget: createFirebaseResolveTarget(graph, serviceMap)
|
|
20009
20156
|
};
|
|
20010
20157
|
}
|
|
@@ -20014,7 +20161,7 @@ init_cjs_shims();
|
|
|
20014
20161
|
|
|
20015
20162
|
// src/connectors/cloudflare/connector.ts
|
|
20016
20163
|
init_cjs_shims();
|
|
20017
|
-
var
|
|
20164
|
+
var import_types74 = require("@neat.is/types");
|
|
20018
20165
|
|
|
20019
20166
|
// src/connectors/cloudflare/client.ts
|
|
20020
20167
|
init_cjs_shims();
|
|
@@ -20178,7 +20325,7 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
20178
20325
|
graph.forEachNode((id, attrs) => {
|
|
20179
20326
|
if (found) return;
|
|
20180
20327
|
const a = attrs;
|
|
20181
|
-
if (a.type ===
|
|
20328
|
+
if (a.type === import_types74.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
|
|
20182
20329
|
found = id;
|
|
20183
20330
|
}
|
|
20184
20331
|
});
|
|
@@ -20190,7 +20337,7 @@ function findMatchingRouteNode(graph, serviceName, method, path77) {
|
|
|
20190
20337
|
graph.forEachNode((id, attrs) => {
|
|
20191
20338
|
if (found) return;
|
|
20192
20339
|
const a = attrs;
|
|
20193
|
-
if (a.type !==
|
|
20340
|
+
if (a.type !== import_types74.NodeType.RouteNode || a.service !== serviceName) return;
|
|
20194
20341
|
if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
|
|
20195
20342
|
const routeMethod = (a.method ?? "").toUpperCase();
|
|
20196
20343
|
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
@@ -20209,11 +20356,11 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
20209
20356
|
};
|
|
20210
20357
|
const mapping = config.workers?.[scriptName];
|
|
20211
20358
|
if (mapping) {
|
|
20212
|
-
const wholeFileId = (0,
|
|
20359
|
+
const wholeFileId = (0, import_types74.fileId)(mapping.service, mapping.entryFile);
|
|
20213
20360
|
return {
|
|
20214
20361
|
targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
|
|
20215
20362
|
serviceName: mapping.service,
|
|
20216
|
-
edgeType:
|
|
20363
|
+
edgeType: import_types74.EdgeType.CALLS
|
|
20217
20364
|
};
|
|
20218
20365
|
}
|
|
20219
20366
|
const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
|
|
@@ -20222,13 +20369,13 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
20222
20369
|
return {
|
|
20223
20370
|
targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
|
|
20224
20371
|
serviceName: fileNode.service,
|
|
20225
|
-
edgeType:
|
|
20372
|
+
edgeType: import_types74.EdgeType.CALLS
|
|
20226
20373
|
};
|
|
20227
20374
|
}
|
|
20228
20375
|
return {
|
|
20229
|
-
targetNodeId: (0,
|
|
20376
|
+
targetNodeId: (0, import_types74.infraId)("cloudflare-worker", scriptName),
|
|
20230
20377
|
serviceName: scriptName,
|
|
20231
|
-
edgeType:
|
|
20378
|
+
edgeType: import_types74.EdgeType.CALLS,
|
|
20232
20379
|
ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
|
|
20233
20380
|
};
|
|
20234
20381
|
};
|
|
@@ -20424,14 +20571,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
|
|
|
20424
20571
|
|
|
20425
20572
|
// src/connectors/neon/resolve.ts
|
|
20426
20573
|
init_cjs_shims();
|
|
20427
|
-
var
|
|
20574
|
+
var import_types78 = require("@neat.is/types");
|
|
20428
20575
|
function createNeonResolveTarget(config) {
|
|
20429
20576
|
return (signal) => {
|
|
20430
20577
|
if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
20431
20578
|
return {
|
|
20432
|
-
targetNodeId: (0,
|
|
20579
|
+
targetNodeId: (0, import_types78.infraId)("sql-table", signal.targetName),
|
|
20433
20580
|
serviceName: config.serviceName,
|
|
20434
|
-
edgeType:
|
|
20581
|
+
edgeType: import_types78.EdgeType.CALLS,
|
|
20435
20582
|
ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
|
|
20436
20583
|
};
|
|
20437
20584
|
};
|
|
@@ -20612,14 +20759,14 @@ function mapLogEntriesToSignals2(entries) {
|
|
|
20612
20759
|
|
|
20613
20760
|
// src/connectors/cloud-run/resolve.ts
|
|
20614
20761
|
init_cjs_shims();
|
|
20615
|
-
var
|
|
20762
|
+
var import_types82 = require("@neat.is/types");
|
|
20616
20763
|
var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
|
|
20617
20764
|
function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
|
|
20618
20765
|
let found = null;
|
|
20619
20766
|
graph.forEachNode((_id, attrs) => {
|
|
20620
20767
|
if (found) return;
|
|
20621
20768
|
const node = attrs;
|
|
20622
|
-
if (node.type !==
|
|
20769
|
+
if (node.type !== import_types82.NodeType.RouteNode) return;
|
|
20623
20770
|
const route = attrs;
|
|
20624
20771
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
20625
20772
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -20635,7 +20782,7 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
20635
20782
|
const identity = parseCloudRunTargetName(signal.targetName);
|
|
20636
20783
|
if (!identity) return null;
|
|
20637
20784
|
const { serviceName: gcpServiceName, method, path: path77 } = identity;
|
|
20638
|
-
const mappedService = config.serviceMap?.[gcpServiceName];
|
|
20785
|
+
const mappedService = config.serviceMap?.[gcpServiceName] ?? (config.inferServices ? inferServiceName(graph, gcpServiceName, method, path77) ?? void 0 : void 0);
|
|
20639
20786
|
if (mappedService) {
|
|
20640
20787
|
const routeNodeId = findMatchingRouteNode2(
|
|
20641
20788
|
graph,
|
|
@@ -20644,13 +20791,13 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
20644
20791
|
normalizePathTemplate(path77)
|
|
20645
20792
|
);
|
|
20646
20793
|
if (routeNodeId) {
|
|
20647
|
-
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType:
|
|
20794
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types82.EdgeType.CALLS };
|
|
20648
20795
|
}
|
|
20649
20796
|
}
|
|
20650
20797
|
return {
|
|
20651
|
-
targetNodeId: (0,
|
|
20798
|
+
targetNodeId: (0, import_types82.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
|
|
20652
20799
|
serviceName: mappedService ?? gcpServiceName,
|
|
20653
|
-
edgeType:
|
|
20800
|
+
edgeType: import_types82.EdgeType.CALLS,
|
|
20654
20801
|
ensureInfraNode: {
|
|
20655
20802
|
kind: CLOUD_RUN_SERVICE_INFRA_KIND,
|
|
20656
20803
|
name: gcpServiceName,
|
|
@@ -20832,14 +20979,14 @@ function mapLogEntriesToSignals3(entries) {
|
|
|
20832
20979
|
|
|
20833
20980
|
// src/connectors/gcp-lb/resolve.ts
|
|
20834
20981
|
init_cjs_shims();
|
|
20835
|
-
var
|
|
20982
|
+
var import_types86 = require("@neat.is/types");
|
|
20836
20983
|
var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
|
|
20837
20984
|
function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
|
|
20838
20985
|
let found = null;
|
|
20839
20986
|
graph.forEachNode((_id, attrs) => {
|
|
20840
20987
|
if (found) return;
|
|
20841
20988
|
const node = attrs;
|
|
20842
|
-
if (node.type !==
|
|
20989
|
+
if (node.type !== import_types86.NodeType.RouteNode) return;
|
|
20843
20990
|
const route = attrs;
|
|
20844
20991
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
20845
20992
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -20855,7 +21002,7 @@ function createGcpLbResolveTarget(graph, config) {
|
|
|
20855
21002
|
const identity = parseGcpLbTargetName(signal.targetName);
|
|
20856
21003
|
if (!identity) return null;
|
|
20857
21004
|
const { backendServiceName, method, path: path77 } = identity;
|
|
20858
|
-
const mappedService = config.backendServiceMap?.[backendServiceName];
|
|
21005
|
+
const mappedService = config.backendServiceMap?.[backendServiceName] ?? (config.inferServices ? inferServiceName(graph, backendServiceName, method, path77) ?? void 0 : void 0);
|
|
20859
21006
|
if (mappedService) {
|
|
20860
21007
|
const routeNodeId = findMatchingRouteNode3(
|
|
20861
21008
|
graph,
|
|
@@ -20864,13 +21011,13 @@ function createGcpLbResolveTarget(graph, config) {
|
|
|
20864
21011
|
normalizePathTemplate(path77)
|
|
20865
21012
|
);
|
|
20866
21013
|
if (routeNodeId) {
|
|
20867
|
-
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType:
|
|
21014
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types86.EdgeType.CALLS };
|
|
20868
21015
|
}
|
|
20869
21016
|
}
|
|
20870
21017
|
return {
|
|
20871
|
-
targetNodeId: (0,
|
|
21018
|
+
targetNodeId: (0, import_types86.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
|
|
20872
21019
|
serviceName: mappedService ?? backendServiceName,
|
|
20873
|
-
edgeType:
|
|
21020
|
+
edgeType: import_types86.EdgeType.CALLS,
|
|
20874
21021
|
ensureInfraNode: {
|
|
20875
21022
|
kind: GCP_LB_BACKEND_INFRA_KIND,
|
|
20876
21023
|
name: backendServiceName,
|
|
@@ -20911,7 +21058,7 @@ function createGcpLbConnector(graph, config = {}) {
|
|
|
20911
21058
|
|
|
20912
21059
|
// src/connectors/render/index.ts
|
|
20913
21060
|
init_cjs_shims();
|
|
20914
|
-
var
|
|
21061
|
+
var import_types89 = require("@neat.is/types");
|
|
20915
21062
|
|
|
20916
21063
|
// src/connectors/render/types.ts
|
|
20917
21064
|
init_cjs_shims();
|
|
@@ -20989,7 +21136,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
20989
21136
|
const out = [];
|
|
20990
21137
|
graph.forEachNode((_id, attrs) => {
|
|
20991
21138
|
const node = attrs;
|
|
20992
|
-
if (node.type !==
|
|
21139
|
+
if (node.type !== import_types89.NodeType.RouteNode) return;
|
|
20993
21140
|
const route = attrs;
|
|
20994
21141
|
if (route.service !== serviceName) return;
|
|
20995
21142
|
out.push({
|
|
@@ -21074,7 +21221,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
21074
21221
|
function createRenderResolveTarget(config) {
|
|
21075
21222
|
return (signal) => {
|
|
21076
21223
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
21077
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
21224
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types89.EdgeType.CALLS };
|
|
21078
21225
|
}
|
|
21079
21226
|
return null;
|
|
21080
21227
|
};
|
|
@@ -21212,21 +21359,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
21212
21359
|
|
|
21213
21360
|
// src/connectors/planetscale/resolve.ts
|
|
21214
21361
|
init_cjs_shims();
|
|
21215
|
-
var
|
|
21362
|
+
var import_types93 = require("@neat.is/types");
|
|
21216
21363
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
21217
21364
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
21218
21365
|
const databaseName = `${config.organization}/${config.database}`;
|
|
21219
21366
|
return (signal, _ctx) => {
|
|
21220
21367
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
21221
|
-
const tableId = (0,
|
|
21368
|
+
const tableId = (0, import_types93.infraId)("sql-table", signal.targetName);
|
|
21222
21369
|
if (graph.hasNode(tableId)) {
|
|
21223
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
21370
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types93.EdgeType.CALLS };
|
|
21224
21371
|
}
|
|
21225
|
-
const providerId = (0,
|
|
21372
|
+
const providerId = (0, import_types93.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
21226
21373
|
return {
|
|
21227
21374
|
targetNodeId: providerId,
|
|
21228
21375
|
serviceName: config.serviceName,
|
|
21229
|
-
edgeType:
|
|
21376
|
+
edgeType: import_types93.EdgeType.CALLS,
|
|
21230
21377
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
21231
21378
|
};
|
|
21232
21379
|
};
|
|
@@ -21491,7 +21638,7 @@ function mapBuildsToSignals(builds, serviceName) {
|
|
|
21491
21638
|
|
|
21492
21639
|
// src/connectors/eas/resolve.ts
|
|
21493
21640
|
init_cjs_shims();
|
|
21494
|
-
var
|
|
21641
|
+
var import_types98 = require("@neat.is/types");
|
|
21495
21642
|
var NO_ENV2 = "unknown";
|
|
21496
21643
|
var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
|
|
21497
21644
|
var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
|
|
@@ -21507,8 +21654,8 @@ function configBasenamesForPhase(phase) {
|
|
|
21507
21654
|
function configNodeService(graph, configNodeId) {
|
|
21508
21655
|
for (const edgeId of graph.inboundEdges(configNodeId)) {
|
|
21509
21656
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
21510
|
-
if (edge.type !==
|
|
21511
|
-
const parsed = (0,
|
|
21657
|
+
if (edge.type !== import_types98.EdgeType.CONFIGURED_BY) continue;
|
|
21658
|
+
const parsed = (0, import_types98.parseFileId)(edge.source);
|
|
21512
21659
|
if (parsed) return parsed.service;
|
|
21513
21660
|
}
|
|
21514
21661
|
return null;
|
|
@@ -21519,7 +21666,7 @@ function findConfigNode(graph, basenames, serviceName) {
|
|
|
21519
21666
|
graph.forEachNode((id, attrs) => {
|
|
21520
21667
|
if (scoped) return;
|
|
21521
21668
|
const node = attrs;
|
|
21522
|
-
if (node.type !==
|
|
21669
|
+
if (node.type !== import_types98.NodeType.ConfigNode) return;
|
|
21523
21670
|
if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
|
|
21524
21671
|
if (anyMatch === null) anyMatch = id;
|
|
21525
21672
|
if (configNodeService(graph, id) === serviceName) scoped = id;
|
|
@@ -21536,13 +21683,13 @@ function createEasResolveTarget(graph) {
|
|
|
21536
21683
|
if (basenames.length > 0) {
|
|
21537
21684
|
const configNodeId = findConfigNode(graph, basenames, serviceName);
|
|
21538
21685
|
if (configNodeId) {
|
|
21539
|
-
return { targetNodeId: configNodeId, serviceName, edgeType:
|
|
21686
|
+
return { targetNodeId: configNodeId, serviceName, edgeType: import_types98.EdgeType.CALLS };
|
|
21540
21687
|
}
|
|
21541
21688
|
}
|
|
21542
21689
|
return {
|
|
21543
21690
|
targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
|
|
21544
21691
|
serviceName,
|
|
21545
|
-
edgeType:
|
|
21692
|
+
edgeType: import_types98.EdgeType.CALLS
|
|
21546
21693
|
};
|
|
21547
21694
|
};
|
|
21548
21695
|
}
|
|
@@ -22270,11 +22417,11 @@ function registerRoutes(scope, ctx) {
|
|
|
22270
22417
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
22271
22418
|
const parsed = [];
|
|
22272
22419
|
for (const c of candidates) {
|
|
22273
|
-
const r =
|
|
22420
|
+
const r = import_types101.DivergenceTypeSchema.safeParse(c);
|
|
22274
22421
|
if (!r.success) {
|
|
22275
22422
|
return reply.code(400).send({
|
|
22276
22423
|
error: `unknown divergence type "${c}"`,
|
|
22277
|
-
allowed:
|
|
22424
|
+
allowed: import_types101.DivergenceTypeSchema.options
|
|
22278
22425
|
});
|
|
22279
22426
|
}
|
|
22280
22427
|
parsed.push(r.data);
|
|
@@ -22670,7 +22817,7 @@ function registerRoutes(scope, ctx) {
|
|
|
22670
22817
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
22671
22818
|
let violations = await log.readAll();
|
|
22672
22819
|
if (req.query.severity) {
|
|
22673
|
-
const sev =
|
|
22820
|
+
const sev = import_types101.PolicySeveritySchema.safeParse(req.query.severity);
|
|
22674
22821
|
if (!sev.success) {
|
|
22675
22822
|
return reply.code(400).send({
|
|
22676
22823
|
error: "invalid severity",
|
|
@@ -22709,7 +22856,7 @@ function registerRoutes(scope, ctx) {
|
|
|
22709
22856
|
scope.post("/policies/check", async (req, reply) => {
|
|
22710
22857
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
22711
22858
|
if (!proj) return;
|
|
22712
|
-
const parsed =
|
|
22859
|
+
const parsed = import_types101.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
22713
22860
|
if (!parsed.success) {
|
|
22714
22861
|
return reply.code(400).send({
|
|
22715
22862
|
error: "invalid /policies/check body",
|