@trustgraph/react-state 1.7.2 → 1.7.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/dist/index.cjs +171 -142
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +172 -143
- package/dist/index.esm.js.map +1 -1
- package/dist/state/explainability.d.ts +1 -1
- package/dist/state/explainability.d.ts.map +1 -1
- package/dist/state/provenance.d.ts +3 -2
- package/dist/state/provenance.d.ts.map +1 -1
- package/dist/utils/explainability.d.ts +18 -22
- package/dist/utils/explainability.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1922,11 +1922,13 @@ const useExplainabilityStore = zustand.create()((set, get) => ({
|
|
|
1922
1922
|
/**
|
|
1923
1923
|
* Explainability utilities for parsing and structuring explain events
|
|
1924
1924
|
*/
|
|
1925
|
-
//
|
|
1925
|
+
// Predicates not yet in client library
|
|
1926
1926
|
const TG_ACTION = client.TG + "action";
|
|
1927
1927
|
const TG_ARGUMENTS = client.TG + "arguments";
|
|
1928
1928
|
const TG_SUBAGENT_GOAL = client.TG + "subagentGoal";
|
|
1929
|
-
|
|
1929
|
+
const TG_CONCEPT = client.TG + "concept";
|
|
1930
|
+
const TG_ENTITY = client.TG + "entity";
|
|
1931
|
+
// RDF type URIs
|
|
1930
1932
|
const TG_AGENT_QUESTION = client.TG + "AgentQuestion";
|
|
1931
1933
|
const TG_ANALYSIS = client.TG + "Analysis";
|
|
1932
1934
|
const TG_TOOL_USE = client.TG + "ToolUse";
|
|
@@ -1934,13 +1936,14 @@ const TG_OBSERVATION = client.TG + "Observation";
|
|
|
1934
1936
|
const TG_THOUGHT_TYPE = client.TG + "Thought";
|
|
1935
1937
|
const TG_REFLECTION_TYPE = client.TG + "Reflection";
|
|
1936
1938
|
const TG_CONCLUSION = client.TG + "Conclusion";
|
|
1937
|
-
const TG_ANSWER = client.TG + "Answer";
|
|
1938
1939
|
const TG_FINDING = client.TG + "Finding";
|
|
1939
|
-
const TG_SYNTHESIS_TYPE = client.TG + "Synthesis";
|
|
1940
1940
|
const TG_DECOMPOSITION = client.TG + "Decomposition";
|
|
1941
|
+
const TG_GROUNDING = client.TG + "Grounding";
|
|
1942
|
+
const TG_EXPLORATION_TYPE = client.TG + "Exploration";
|
|
1943
|
+
const TG_FOCUS_TYPE = client.TG + "Focus";
|
|
1941
1944
|
// ── Helpers ─────────────────────────────────────────────────────────
|
|
1942
1945
|
/**
|
|
1943
|
-
* Extract event type from explainId URI (graph-rag
|
|
1946
|
+
* Extract event type from explainId URI (graph-rag fallback)
|
|
1944
1947
|
*/
|
|
1945
1948
|
function getEventType(explainId) {
|
|
1946
1949
|
if (explainId.includes("question"))
|
|
@@ -1953,9 +1956,6 @@ function getEventType(explainId) {
|
|
|
1953
1956
|
return "synthesis";
|
|
1954
1957
|
return "unknown";
|
|
1955
1958
|
}
|
|
1956
|
-
/**
|
|
1957
|
-
* Get term value from a Term object
|
|
1958
|
-
*/
|
|
1959
1959
|
function getTermValue$1(term) {
|
|
1960
1960
|
if (!term)
|
|
1961
1961
|
return "";
|
|
@@ -1964,7 +1964,6 @@ function getTermValue$1(term) {
|
|
|
1964
1964
|
if (term.t === "l")
|
|
1965
1965
|
return term.v || "";
|
|
1966
1966
|
if (term.t === "t" && term.tr) {
|
|
1967
|
-
// Quoted triple - return a serialized form
|
|
1968
1967
|
const s = getTermValue$1(term.tr.s);
|
|
1969
1968
|
const p = getTermValue$1(term.tr.p);
|
|
1970
1969
|
const o = getTermValue$1(term.tr.o);
|
|
@@ -1972,9 +1971,6 @@ function getTermValue$1(term) {
|
|
|
1972
1971
|
}
|
|
1973
1972
|
return "";
|
|
1974
1973
|
}
|
|
1975
|
-
/**
|
|
1976
|
-
* Extract quoted triple from a Term
|
|
1977
|
-
*/
|
|
1978
1974
|
function extractQuotedTriple(term) {
|
|
1979
1975
|
if (term.t === "t" && term.tr) {
|
|
1980
1976
|
return {
|
|
@@ -1985,9 +1981,15 @@ function extractQuotedTriple(term) {
|
|
|
1985
1981
|
}
|
|
1986
1982
|
return null;
|
|
1987
1983
|
}
|
|
1988
|
-
// ──
|
|
1989
|
-
/**
|
|
1990
|
-
|
|
1984
|
+
// ── RDF type detection ──────────────────────────────────────────────
|
|
1985
|
+
/**
|
|
1986
|
+
* Map RDF type URI → event type (first match wins).
|
|
1987
|
+
* Agent-specific types only — shared types like tg:Synthesis and
|
|
1988
|
+
* tg:Answer are excluded to avoid catching graph-rag events.
|
|
1989
|
+
* Grounding, Exploration, Focus are included since they now carry
|
|
1990
|
+
* embedded triples with their RDF type.
|
|
1991
|
+
*/
|
|
1992
|
+
const RDF_TYPE_CHECKS = [
|
|
1991
1993
|
[TG_AGENT_QUESTION, "agent-question"],
|
|
1992
1994
|
[TG_DECOMPOSITION, "decomposition"],
|
|
1993
1995
|
[TG_ANALYSIS, "analysis"],
|
|
@@ -1997,12 +1999,12 @@ const AGENT_TYPE_CHECKS = [
|
|
|
1997
1999
|
[TG_REFLECTION_TYPE, "reflection"],
|
|
1998
2000
|
[TG_CONCLUSION, "conclusion"],
|
|
1999
2001
|
[TG_FINDING, "conclusion"],
|
|
2000
|
-
[
|
|
2001
|
-
[
|
|
2002
|
+
[TG_GROUNDING, "grounding"],
|
|
2003
|
+
[TG_EXPLORATION_TYPE, "exploration"],
|
|
2004
|
+
[TG_FOCUS_TYPE, "focus"],
|
|
2002
2005
|
];
|
|
2003
2006
|
/**
|
|
2004
2007
|
* Detect event type from RDF types in embedded triples.
|
|
2005
|
-
* Returns an agent event type if matched, "unknown" otherwise.
|
|
2006
2008
|
*/
|
|
2007
2009
|
function getEventTypeFromTriples(triples) {
|
|
2008
2010
|
const types = new Set();
|
|
@@ -2011,7 +2013,7 @@ function getEventTypeFromTriples(triples) {
|
|
|
2011
2013
|
types.add(getTermValue$1(t.o));
|
|
2012
2014
|
}
|
|
2013
2015
|
}
|
|
2014
|
-
for (const [typeUri, eventType] of
|
|
2016
|
+
for (const [typeUri, eventType] of RDF_TYPE_CHECKS) {
|
|
2015
2017
|
if (types.has(typeUri))
|
|
2016
2018
|
return eventType;
|
|
2017
2019
|
}
|
|
@@ -2031,38 +2033,48 @@ function extractCommonFields(triples) {
|
|
|
2031
2033
|
}
|
|
2032
2034
|
return { label, derivedFrom };
|
|
2033
2035
|
}
|
|
2034
|
-
|
|
2036
|
+
/**
|
|
2037
|
+
* Extract inline edges from triples (tg:edge quoted triples).
|
|
2038
|
+
* Returns SelectedEdge objects with URIs — labels resolved later.
|
|
2039
|
+
*/
|
|
2040
|
+
function extractInlineEdges(triples) {
|
|
2041
|
+
const edges = [];
|
|
2042
|
+
for (const t of triples) {
|
|
2043
|
+
if (getTermValue$1(t.p) === client.TG_EDGE && t.o.t === "t" && t.o.tr) {
|
|
2044
|
+
const edge = extractQuotedTriple(t.o);
|
|
2045
|
+
if (edge) {
|
|
2046
|
+
edges.push({ edge });
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
return edges;
|
|
2051
|
+
}
|
|
2052
|
+
// ── Parsers ─────────────────────────────────────────────────────────
|
|
2035
2053
|
function parseQuestionTriples(explainId, explainGraph, triples) {
|
|
2036
|
-
const event = {
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
for (const triple of triples) {
|
|
2042
|
-
const p = getTermValue$1(triple.p);
|
|
2043
|
-
const o = getTermValue$1(triple.o);
|
|
2044
|
-
if (p === client.TG_QUERY) {
|
|
2054
|
+
const event = { type: "question", explainId, explainGraph };
|
|
2055
|
+
for (const t of triples) {
|
|
2056
|
+
const p = getTermValue$1(t.p);
|
|
2057
|
+
const o = getTermValue$1(t.o);
|
|
2058
|
+
if (p === client.TG_QUERY)
|
|
2045
2059
|
event.query = o;
|
|
2046
|
-
|
|
2047
|
-
else if (p === client.PROV_STARTED_AT_TIME) {
|
|
2060
|
+
else if (p === client.PROV_STARTED_AT_TIME)
|
|
2048
2061
|
event.timestamp = o;
|
|
2049
|
-
}
|
|
2050
2062
|
}
|
|
2051
2063
|
return event;
|
|
2052
2064
|
}
|
|
2053
2065
|
function parseExplorationTriples(explainId, explainGraph, triples) {
|
|
2054
|
-
const event = {
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
const p = getTermValue$1(triple.p);
|
|
2061
|
-
const o = getTermValue$1(triple.o);
|
|
2062
|
-
if (p === client.TG_EDGE_COUNT) {
|
|
2066
|
+
const event = { type: "exploration", explainId, explainGraph };
|
|
2067
|
+
const entities = [];
|
|
2068
|
+
for (const t of triples) {
|
|
2069
|
+
const p = getTermValue$1(t.p);
|
|
2070
|
+
const o = getTermValue$1(t.o);
|
|
2071
|
+
if (p === client.TG_EDGE_COUNT)
|
|
2063
2072
|
event.edgeCount = parseInt(o, 10);
|
|
2064
|
-
|
|
2073
|
+
if (p === TG_ENTITY && o)
|
|
2074
|
+
entities.push(o);
|
|
2065
2075
|
}
|
|
2076
|
+
if (entities.length > 0)
|
|
2077
|
+
event.entities = entities;
|
|
2066
2078
|
return event;
|
|
2067
2079
|
}
|
|
2068
2080
|
function parseFocusTriples(explainId, explainGraph, triples) {
|
|
@@ -2072,27 +2084,28 @@ function parseFocusTriples(explainId, explainGraph, triples) {
|
|
|
2072
2084
|
explainGraph,
|
|
2073
2085
|
edgeSelectionUris: [],
|
|
2074
2086
|
};
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
const
|
|
2087
|
+
// Collect edge selection URIs (old format)
|
|
2088
|
+
for (const t of triples) {
|
|
2089
|
+
const p = getTermValue$1(t.p);
|
|
2090
|
+
const o = getTermValue$1(t.o);
|
|
2078
2091
|
if (p === client.TG_SELECTED_EDGE && typeof o === "string") {
|
|
2079
2092
|
event.edgeSelectionUris.push(o);
|
|
2080
2093
|
}
|
|
2081
2094
|
}
|
|
2095
|
+
// Extract inline edges (new format: tg:edge with quoted triples)
|
|
2096
|
+
const inlineEdges = extractInlineEdges(triples);
|
|
2097
|
+
if (inlineEdges.length > 0) {
|
|
2098
|
+
event.selectedEdges = inlineEdges;
|
|
2099
|
+
}
|
|
2082
2100
|
return event;
|
|
2083
2101
|
}
|
|
2084
2102
|
function parseSynthesisTriples(explainId, explainGraph, triples) {
|
|
2085
|
-
const event = {
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
for (const triple of triples) {
|
|
2091
|
-
const p = getTermValue$1(triple.p);
|
|
2092
|
-
const o = getTermValue$1(triple.o);
|
|
2093
|
-
if (p === client.TG_CONTENT) {
|
|
2103
|
+
const event = { type: "synthesis", explainId, explainGraph };
|
|
2104
|
+
for (const t of triples) {
|
|
2105
|
+
const p = getTermValue$1(t.p);
|
|
2106
|
+
const o = getTermValue$1(t.o);
|
|
2107
|
+
if (p === client.TG_CONTENT)
|
|
2094
2108
|
event.contentLength = o.length;
|
|
2095
|
-
}
|
|
2096
2109
|
}
|
|
2097
2110
|
return event;
|
|
2098
2111
|
}
|
|
@@ -2101,24 +2114,28 @@ function parseEdgeSelectionTriples(triples) {
|
|
|
2101
2114
|
let reasoning = null;
|
|
2102
2115
|
for (const triple of triples) {
|
|
2103
2116
|
const p = getTermValue$1(triple.p);
|
|
2104
|
-
if (p === client.TG_EDGE)
|
|
2117
|
+
if (p === client.TG_EDGE)
|
|
2105
2118
|
edge = extractQuotedTriple(triple.o);
|
|
2106
|
-
|
|
2107
|
-
else if (p === client.TG_REASONING) {
|
|
2119
|
+
else if (p === client.TG_REASONING)
|
|
2108
2120
|
reasoning = getTermValue$1(triple.o);
|
|
2109
|
-
}
|
|
2110
2121
|
}
|
|
2111
2122
|
return { edge, reasoning };
|
|
2112
2123
|
}
|
|
2113
|
-
|
|
2124
|
+
function parseGroundingTriples(explainId, explainGraph, triples) {
|
|
2125
|
+
const { label, derivedFrom } = extractCommonFields(triples);
|
|
2126
|
+
const concepts = [];
|
|
2127
|
+
for (const t of triples) {
|
|
2128
|
+
const p = getTermValue$1(t.p);
|
|
2129
|
+
const o = getTermValue$1(t.o);
|
|
2130
|
+
if (p === TG_CONCEPT && o)
|
|
2131
|
+
concepts.push(o);
|
|
2132
|
+
}
|
|
2133
|
+
return { type: "grounding", explainId, explainGraph, label, concepts, derivedFrom };
|
|
2134
|
+
}
|
|
2114
2135
|
function parseAgentQuestionTriples(explainId, explainGraph, triples) {
|
|
2115
2136
|
const { label, derivedFrom } = extractCommonFields(triples);
|
|
2116
2137
|
const event = {
|
|
2117
|
-
type: "agent-question",
|
|
2118
|
-
explainId,
|
|
2119
|
-
explainGraph,
|
|
2120
|
-
label,
|
|
2121
|
-
derivedFrom,
|
|
2138
|
+
type: "agent-question", explainId, explainGraph, label, derivedFrom,
|
|
2122
2139
|
};
|
|
2123
2140
|
for (const t of triples) {
|
|
2124
2141
|
const p = getTermValue$1(t.p);
|
|
@@ -2139,23 +2156,12 @@ function parseDecompositionTriples(explainId, explainGraph, triples) {
|
|
|
2139
2156
|
if (p === TG_SUBAGENT_GOAL && o)
|
|
2140
2157
|
goals.push(o);
|
|
2141
2158
|
}
|
|
2142
|
-
return {
|
|
2143
|
-
type: "decomposition",
|
|
2144
|
-
explainId,
|
|
2145
|
-
explainGraph,
|
|
2146
|
-
label,
|
|
2147
|
-
goals,
|
|
2148
|
-
derivedFrom,
|
|
2149
|
-
};
|
|
2159
|
+
return { type: "decomposition", explainId, explainGraph, label, goals, derivedFrom };
|
|
2150
2160
|
}
|
|
2151
2161
|
function parseAnalysisTriples(explainId, explainGraph, triples) {
|
|
2152
2162
|
const { label, derivedFrom } = extractCommonFields(triples);
|
|
2153
2163
|
const event = {
|
|
2154
|
-
type: "analysis",
|
|
2155
|
-
explainId,
|
|
2156
|
-
explainGraph,
|
|
2157
|
-
label,
|
|
2158
|
-
derivedFrom,
|
|
2164
|
+
type: "analysis", explainId, explainGraph, label, derivedFrom,
|
|
2159
2165
|
};
|
|
2160
2166
|
for (const t of triples) {
|
|
2161
2167
|
const p = getTermValue$1(t.p);
|
|
@@ -2169,34 +2175,22 @@ function parseAnalysisTriples(explainId, explainGraph, triples) {
|
|
|
2169
2175
|
}
|
|
2170
2176
|
function parseReflectionTriples(explainId, explainGraph, triples) {
|
|
2171
2177
|
const { label, derivedFrom } = extractCommonFields(triples);
|
|
2172
|
-
return {
|
|
2173
|
-
type: "reflection",
|
|
2174
|
-
explainId,
|
|
2175
|
-
explainGraph,
|
|
2176
|
-
label,
|
|
2177
|
-
derivedFrom,
|
|
2178
|
-
};
|
|
2178
|
+
return { type: "reflection", explainId, explainGraph, label, derivedFrom };
|
|
2179
2179
|
}
|
|
2180
2180
|
function parseConclusionTriples(explainId, explainGraph, triples) {
|
|
2181
2181
|
const { label, derivedFrom } = extractCommonFields(triples);
|
|
2182
|
-
return {
|
|
2183
|
-
type: "conclusion",
|
|
2184
|
-
explainId,
|
|
2185
|
-
explainGraph,
|
|
2186
|
-
label,
|
|
2187
|
-
derivedFrom,
|
|
2188
|
-
};
|
|
2182
|
+
return { type: "conclusion", explainId, explainGraph, label, derivedFrom };
|
|
2189
2183
|
}
|
|
2190
2184
|
// ── Unified parser ──────────────────────────────────────────────────
|
|
2191
2185
|
/**
|
|
2192
2186
|
* Parse triples into a structured event.
|
|
2193
|
-
* Tries RDF type detection first
|
|
2194
|
-
* Returns null for events with no triples
|
|
2187
|
+
* Tries RDF type detection first, then URI patterns as fallback.
|
|
2188
|
+
* Returns null for events with no triples.
|
|
2195
2189
|
*/
|
|
2196
2190
|
function parseExplainTriples(explainId, explainGraph, triples) {
|
|
2197
2191
|
if (triples.length === 0)
|
|
2198
2192
|
return null;
|
|
2199
|
-
// Try RDF type detection first
|
|
2193
|
+
// Try RDF type detection first
|
|
2200
2194
|
const rdfEventType = getEventTypeFromTriples(triples);
|
|
2201
2195
|
if (rdfEventType !== "unknown") {
|
|
2202
2196
|
switch (rdfEventType) {
|
|
@@ -2210,6 +2204,12 @@ function parseExplainTriples(explainId, explainGraph, triples) {
|
|
|
2210
2204
|
return parseReflectionTriples(explainId, explainGraph, triples);
|
|
2211
2205
|
case "conclusion":
|
|
2212
2206
|
return parseConclusionTriples(explainId, explainGraph, triples);
|
|
2207
|
+
case "grounding":
|
|
2208
|
+
return parseGroundingTriples(explainId, explainGraph, triples);
|
|
2209
|
+
case "exploration":
|
|
2210
|
+
return parseExplorationTriples(explainId, explainGraph, triples);
|
|
2211
|
+
case "focus":
|
|
2212
|
+
return parseFocusTriples(explainId, explainGraph, triples);
|
|
2213
2213
|
}
|
|
2214
2214
|
}
|
|
2215
2215
|
// Fall back to URI pattern detection (graph-rag events)
|
|
@@ -2230,8 +2230,10 @@ function parseExplainTriples(explainId, explainGraph, triples) {
|
|
|
2230
2230
|
|
|
2231
2231
|
/**
|
|
2232
2232
|
* Hook for tracing provenance chains in the knowledge graph
|
|
2233
|
-
* Follows
|
|
2233
|
+
* Follows tg:contains to find subgraphs, then prov:wasDerivedFrom
|
|
2234
|
+
* to trace chunk → page → document chains
|
|
2234
2235
|
*/
|
|
2236
|
+
const TG_CONTAINS = client.TG + "contains";
|
|
2235
2237
|
/**
|
|
2236
2238
|
* Hook for tracing provenance chains
|
|
2237
2239
|
*/
|
|
@@ -2328,13 +2330,13 @@ const useProvenance = (options = {}) => {
|
|
|
2328
2330
|
}
|
|
2329
2331
|
}, [maxDepth, resolveLabel, queryDerivedFrom]);
|
|
2330
2332
|
/**
|
|
2331
|
-
*
|
|
2333
|
+
* Find subgraphs that contain an edge via tg:contains with a quoted triple
|
|
2332
2334
|
*/
|
|
2333
|
-
const
|
|
2335
|
+
const queryContainingSubgraphs = react.useCallback(async (s, p, o) => {
|
|
2334
2336
|
if (!isConnected())
|
|
2335
2337
|
return [];
|
|
2336
2338
|
try {
|
|
2337
|
-
// Build the quoted triple term
|
|
2339
|
+
// Build the quoted triple term for the edge
|
|
2338
2340
|
const quotedTriple = {
|
|
2339
2341
|
t: "t",
|
|
2340
2342
|
tr: {
|
|
@@ -2347,7 +2349,7 @@ const useProvenance = (options = {}) => {
|
|
|
2347
2349
|
};
|
|
2348
2350
|
const triples = await socket
|
|
2349
2351
|
.flow(effectiveFlow)
|
|
2350
|
-
.triplesQuery(undefined, { t: "i", i:
|
|
2352
|
+
.triplesQuery(undefined, { t: "i", i: TG_CONTAINS }, quotedTriple, 10, collection);
|
|
2351
2353
|
return triples.map((t) => getTermValue$1(t.s));
|
|
2352
2354
|
}
|
|
2353
2355
|
catch {
|
|
@@ -2355,20 +2357,21 @@ const useProvenance = (options = {}) => {
|
|
|
2355
2357
|
}
|
|
2356
2358
|
}, [socket, effectiveFlow, collection, isConnected]);
|
|
2357
2359
|
/**
|
|
2358
|
-
* Trace provenance for an edge
|
|
2360
|
+
* Trace provenance for an edge — find containing subgraph, then follow
|
|
2361
|
+
* wasDerivedFrom chain: subgraph → chunk → page → document
|
|
2359
2362
|
*/
|
|
2360
2363
|
const traceEdgeProvenance = react.useCallback(async (s, p, o) => {
|
|
2361
2364
|
setIsTracing(true);
|
|
2362
2365
|
try {
|
|
2363
|
-
// Find
|
|
2364
|
-
const
|
|
2365
|
-
// For each reifying statement, trace its provenance chain
|
|
2366
|
+
// Find subgraphs containing this edge
|
|
2367
|
+
const subgraphUris = await queryContainingSubgraphs(s, p, o);
|
|
2366
2368
|
const chains = [];
|
|
2367
|
-
for (const
|
|
2368
|
-
//
|
|
2369
|
-
const
|
|
2370
|
-
if (
|
|
2371
|
-
|
|
2369
|
+
for (const subgraphUri of subgraphUris) {
|
|
2370
|
+
// Follow wasDerivedFrom from the subgraph to the chunk
|
|
2371
|
+
const chunkUri = await queryDerivedFrom(subgraphUri);
|
|
2372
|
+
if (chunkUri) {
|
|
2373
|
+
// Trace the full chain from chunk upward
|
|
2374
|
+
const chain = await traceChain(chunkUri);
|
|
2372
2375
|
chains.push(chain);
|
|
2373
2376
|
}
|
|
2374
2377
|
}
|
|
@@ -2377,7 +2380,7 @@ const useProvenance = (options = {}) => {
|
|
|
2377
2380
|
finally {
|
|
2378
2381
|
setIsTracing(false);
|
|
2379
2382
|
}
|
|
2380
|
-
}, [
|
|
2383
|
+
}, [queryContainingSubgraphs, queryDerivedFrom, traceChain]);
|
|
2381
2384
|
/**
|
|
2382
2385
|
* Clear the label cache
|
|
2383
2386
|
*/
|
|
@@ -2479,56 +2482,82 @@ const useExplainability = (options = {}) => {
|
|
|
2479
2482
|
setSession(updater);
|
|
2480
2483
|
onUpdateRef.current?.(sessionRef.current);
|
|
2481
2484
|
}, []);
|
|
2482
|
-
const
|
|
2485
|
+
const AGENT_STEP_TYPES = new Set([
|
|
2483
2486
|
"agent-question", "decomposition", "analysis", "reflection", "conclusion",
|
|
2487
|
+
"grounding",
|
|
2484
2488
|
]);
|
|
2489
|
+
/**
|
|
2490
|
+
* Resolve labels for inline edges (edges already extracted, just need labels)
|
|
2491
|
+
*/
|
|
2492
|
+
const resolveEdgeLabels = react.useCallback(async (focusEvent) => {
|
|
2493
|
+
if (!focusEvent.selectedEdges || focusEvent.selectedEdges.length === 0) {
|
|
2494
|
+
return focusEvent;
|
|
2495
|
+
}
|
|
2496
|
+
const resolved = await Promise.all(focusEvent.selectedEdges.map(async (se) => {
|
|
2497
|
+
const [sLabel, pLabel, oLabel] = await Promise.all([
|
|
2498
|
+
resolveLabel(se.edge.s),
|
|
2499
|
+
resolveLabel(se.edge.p),
|
|
2500
|
+
resolveLabel(se.edge.o),
|
|
2501
|
+
]);
|
|
2502
|
+
let sources;
|
|
2503
|
+
if (traceProvenance) {
|
|
2504
|
+
const chains = await traceEdgeProvenance(se.edge.s, se.edge.p, se.edge.o);
|
|
2505
|
+
if (chains.length > 0) {
|
|
2506
|
+
sources = chains.map((c) => c.chain).flat();
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
return {
|
|
2510
|
+
...se,
|
|
2511
|
+
labels: { s: sLabel, p: pLabel, o: oLabel },
|
|
2512
|
+
sources,
|
|
2513
|
+
};
|
|
2514
|
+
}));
|
|
2515
|
+
return { ...focusEvent, selectedEdges: resolved };
|
|
2516
|
+
}, [resolveLabel, traceProvenance, traceEdgeProvenance]);
|
|
2485
2517
|
/**
|
|
2486
2518
|
* Process a single explain event
|
|
2487
2519
|
*/
|
|
2488
2520
|
const processEvent = react.useCallback(async (event) => {
|
|
2489
|
-
// Use embedded triples directly from the event
|
|
2490
2521
|
const triples = event.explainTriples ?? [];
|
|
2491
|
-
// Parse into structured data
|
|
2492
2522
|
const parsed = parseExplainTriples(event.explainId, event.explainGraph, triples);
|
|
2493
2523
|
if (!parsed)
|
|
2494
2524
|
return;
|
|
2495
|
-
if (
|
|
2496
|
-
// Agent
|
|
2525
|
+
if (AGENT_STEP_TYPES.has(parsed.type)) {
|
|
2526
|
+
// Agent step — append to timeline
|
|
2497
2527
|
updateSession((prev) => ({
|
|
2498
2528
|
...prev,
|
|
2499
2529
|
agentSteps: [...(prev.agentSteps || []), parsed],
|
|
2500
2530
|
}));
|
|
2501
2531
|
}
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
break;
|
|
2532
|
+
// Graph-RAG fields — populate regardless (agent produces these too)
|
|
2533
|
+
switch (parsed.type) {
|
|
2534
|
+
case "question":
|
|
2535
|
+
updateSession((prev) => ({ ...prev, question: parsed }));
|
|
2536
|
+
break;
|
|
2537
|
+
case "exploration":
|
|
2538
|
+
updateSession((prev) => ({ ...prev, exploration: parsed }));
|
|
2539
|
+
break;
|
|
2540
|
+
case "focus": {
|
|
2541
|
+
updateSession((prev) => ({ ...prev, focus: parsed }));
|
|
2542
|
+
// Resolve labels for inline edges, or unpack old-format edges
|
|
2543
|
+
const focusEvent = parsed;
|
|
2544
|
+
if (focusEvent.selectedEdges && focusEvent.selectedEdges.length > 0) {
|
|
2545
|
+
// New format: edges already extracted, resolve labels
|
|
2546
|
+
const resolved = await resolveEdgeLabels(focusEvent);
|
|
2547
|
+
updateSession((prev) => ({ ...prev, focus: resolved }));
|
|
2519
2548
|
}
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
...prev,
|
|
2527
|
-
focus: unpackedFocus,
|
|
2528
|
-
}));
|
|
2549
|
+
else if (focusEvent.edgeSelectionUris.length > 0) {
|
|
2550
|
+
// Old format: unpack edge selection URIs
|
|
2551
|
+
const unpacked = await unpackFocusEvent(focusEvent, triples);
|
|
2552
|
+
updateSession((prev) => ({ ...prev, focus: unpacked }));
|
|
2553
|
+
}
|
|
2554
|
+
break;
|
|
2529
2555
|
}
|
|
2556
|
+
case "synthesis":
|
|
2557
|
+
updateSession((prev) => ({ ...prev, synthesis: parsed }));
|
|
2558
|
+
break;
|
|
2530
2559
|
}
|
|
2531
|
-
}, [unpackFocusEvent, updateSession]);
|
|
2560
|
+
}, [unpackFocusEvent, resolveEdgeLabels, updateSession]);
|
|
2532
2561
|
/**
|
|
2533
2562
|
* Process the unpack queue
|
|
2534
2563
|
*/
|