@aiquants/enrichment-react-router 0.1.1
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/LICENSE +21 -0
- package/README.md +13 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +259 -0
- package/dist/index.d.ts +259 -0
- package/dist/index.js +2 -0
- package/package.json +89 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AI Quants
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @aiquants/enrichment-react-router
|
|
2
|
+
|
|
3
|
+
React Router (v7 / v8) adapter and turnkey operations console for Storage AI Enrichment & Knowledge Governance.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@aiquants/enrichment-react-router` encapsulates the full administrative lifecycle of enterprise knowledge indexing, RAG pipelines, graph stores, vector indices, and peripheral database health inspection into a single mountable route.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @aiquants/enrichment-react-router
|
|
13
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var Q=Object.defineProperty;var ge=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var ye=Object.prototype.hasOwnProperty;var Se=(t,e)=>{for(var o in e)Q(t,o,{get:e[o],enumerable:!0})},be=(t,e,o,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of fe(e))!ye.call(t,i)&&i!==o&&Q(t,i,{get:()=>e[i],enumerable:!(s=ge(e,i))||s.enumerable});return t};var he=t=>be(Q({},"__esModule",{value:!0}),t);var ke={};Se(ke,{StorageAdminConsoleView:()=>$,checkAllSystemHealth:()=>J,checkBackendApiHealth:()=>le,checkNeo4jHealth:()=>ie,checkQdrantHealth:()=>se,checkRedisHealth:()=>ae,checkSqlServerHealth:()=>oe,createStorageAdminApp:()=>Ce,createStorageAdminServer:()=>W});module.exports=he(ke);var F=require("@aiquants/enrichment-core"),R=require("@aiquants/enrichment-react"),v=require("@aiquants/governance-react"),T=require("react"),j=require("react-router"),c=require("react/jsx-runtime"),X="tab",L=[{key:"search",label:"\u30E1\u30BF\u30C7\u30FC\u30BF\u691C\u7D22\u30EF\u30FC\u30AF\u30D9\u30F3\u30C1"},{key:"ingest",label:"\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u53D6\u308A\u8FBC\u307F & \u30E1\u30BF\u751F\u6210"},{key:"rag-pipeline",label:"RAG \u5B9F\u884C\u57FA\u76E4 & \u63A5\u7D9A\u72B6\u614B"},{key:"knowledge-graph",label:"\u30CA\u30EC\u30C3\u30B8\u30B0\u30E9\u30D5\u63A2\u7D22"},{key:"parameters",label:"\u30E2\u30C7\u30EB & \u30D1\u30E9\u30E1\u30FC\u30BF\u8A2D\u5B9A"},{key:"prompts",label:"\u30D7\u30ED\u30F3\u30D7\u30C8 & \u30C9\u30E9\u30A4\u30E9\u30F3"},{key:"data-retention",label:"\u30C7\u30FC\u30BF\u4FDD\u6301 & \u6574\u5408\u6027\u76E3\u67FB"}];function ve(t){return t!==null&&L.some(e=>e.key===t)}var Re={state:"idle",formData:null,data:null,submit:()=>Promise.resolve()};function ee({data:t,fetcher:e,renderHeader:o,onTraverseGraph:s,onBrowseGraphNodes:i,onSimulateGovernance:n,onRefreshIngestQueue:a}){let[l,p]=(0,T.useState)(null),[m,f]=(0,T.useState)(null),[y,b]=(0,T.useState)(!1),d=(0,T.useCallback)((r,S)=>{i!==void 0&&(b(!0),i(r,S).then(h=>{b(!1),f(h.ok?null:h.reason),h.ok&&p(h.page)}))},[i]),[k,E]=(0,j.useSearchParams)(),P=k.get(X),g=ve(P)?P:L[0].key,N=r=>{E(S=>{let h=new URLSearchParams(S);return h.set(X,r),h},{replace:!1,preventScrollReset:!0})},x=we(t.recentIngestItems,a,g==="ingest"),u=x===t.recentIngestItems?t:{...t,recentIngestItems:x===void 0?void 0:[...x]},w=(0,T.useRef)({}),I=(r,S)=>{let h=L.length-1,_;if(r.key==="ArrowRight"||r.key==="ArrowDown")_=S===h?0:S+1;else if(r.key==="ArrowLeft"||r.key==="ArrowUp")_=S===0?h:S-1;else if(r.key==="Home")_=0;else if(r.key==="End")_=h;else return;r.preventDefault();let U=L[_].key;N(U),w.current[U]?.focus()},O={...u.featureFlags};if(e.formData&&e.formData.get("intent")==="toggle_flag"){let r=String(e.formData.get("flagKey")??""),S=String(e.formData.get("enabled")??"")==="true";r&&(O[r]=S)}let D=e.data?.error,K=e.data&&"inspection"in e.data?e.data.inspection:void 0,q=e.state!=="idle"&&e.formData?.get("intent")==="inspect_uri",G=e.state!=="idle"&&e.formData?.get("intent")==="ingest_document";return(0,c.jsxs)("div",{className:"container mx-auto space-y-6 p-6 font-sans text-slate-900","data-testid":"storage-admin-console",children:[D&&(0,c.jsx)("div",{className:"rounded-lg border border-red-200 bg-red-50 p-4 font-medium text-red-700 text-sm shadow-sm",role:"alert","data-testid":"storage-admin-error-alert",children:D}),o?o({title:"\u30B9\u30C8\u30EC\u30FC\u30B8 AI \u30A8\u30F3\u30EA\u30C3\u30C1\u30E1\u30F3\u30C8 & \u30AC\u30D0\u30CA\u30F3\u30B9\u904B\u7528\u7BA1\u7406",tenantId:u.tenantId}):(0,c.jsxs)("header",{className:"flex flex-col justify-between gap-2 border-slate-200 border-b pb-4 md:flex-row md:items-center",children:[(0,c.jsxs)("div",{children:[(0,c.jsx)("h1",{className:"font-bold text-2xl tracking-tight",children:"\u30B9\u30C8\u30EC\u30FC\u30B8 AI \u30A8\u30F3\u30EA\u30C3\u30C1\u30E1\u30F3\u30C8 & \u30AC\u30D0\u30CA\u30F3\u30B9\u904B\u7528\u7BA1\u7406"}),(0,c.jsxs)("p",{className:"mt-1 text-slate-500 text-sm",children:["\u30C6\u30CA\u30F3\u30C8: ",(0,c.jsx)("code",{className:"font-semibold text-slate-800",children:u.tenantId})," | \u5168\u30B7\u30B9\u30C6\u30E0\u72B6\u614B\u30FB\u30D1\u30E9\u30E1\u30FC\u30BF\u5236\u5FA1\u30FB\u6574\u5408\u6027\u76E3\u67FB"]})]}),(0,c.jsx)("div",{className:"flex items-center gap-2",children:(0,c.jsxs)("button",{type:"button","data-testid":"header-health-status-button",onClick:()=>N("rag-pipeline"),className:"inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-1.5 font-medium text-slate-700 text-xs transition-colors hover:bg-slate-100",children:[(0,c.jsx)("span",{className:`h-2 w-2 rounded-full ${u.systemHealth.allHealthy?"bg-emerald-500":"bg-amber-500"}`}),(0,c.jsxs)("span",{children:["\u5468\u8FBA\u6A5F\u80FD: ",u.systemHealth.allHealthy?"\u5168\u30B5\u30FC\u30D3\u30B9\u6B63\u5E38":"\u63A5\u7D9A\u8981\u78BA\u8A8D"]})]})})]}),(0,c.jsxs)("div",{className:"w-full space-y-6",children:[(0,c.jsx)("div",{className:"grid w-full grid-cols-2 gap-1 rounded-xl bg-slate-100 p-1 md:grid-cols-8",role:"tablist","aria-label":"Storage Administration Console Tabs",children:L.map((r,S)=>{let h=g===r.key;return(0,c.jsx)("button",{id:`tab-${r.key}`,type:"button",role:"tab",ref:_=>{w.current[r.key]=_},"aria-selected":h,"aria-controls":`panel-${r.key}`,tabIndex:h?0:-1,"data-testid":`tab-trigger-${r.key}`,onKeyDown:_=>I(_,S),onClick:()=>N(r.key),className:`rounded-lg px-3 py-2.5 text-center font-medium text-sm transition-all ${h?"bg-white text-slate-900 shadow-sm":"text-slate-600 hover:bg-slate-200/50 hover:text-slate-900"}`,children:r.label},r.key)})}),g==="search"&&(0,c.jsx)("div",{role:"tabpanel",id:"panel-search","aria-labelledby":"tab-search",className:"space-y-6","data-testid":"tab-content-search",children:(0,c.jsx)(R.MetadataSearchWorkbench,{tenantId:u.tenantId,circuitBreakerStatus:u.circuitBreakerStatus})}),g==="ingest"&&(0,c.jsx)("div",{role:"tabpanel",id:"panel-ingest","aria-labelledby":"tab-ingest",className:"space-y-6","data-testid":"tab-content-ingest",children:(0,c.jsx)(R.DocumentIngestConsole,{tenantId:u.tenantId,policies:u.confidentialityPolicies,recentItems:u.recentIngestItems,inspectionResult:K,isInspecting:q,isSubmitting:G,onInspectUri:r=>{e.submit({intent:"inspect_uri",fileUri:r},{method:"post"})},onIngestDocument:r=>{e.submit({intent:"ingest_document",payload:JSON.stringify(r)},{method:"post"})},onRetryItem:r=>{e.submit({intent:"retry_job",fileId:String(r)},{method:"post"})}})}),g==="rag-pipeline"&&(0,c.jsxs)("div",{role:"tabpanel",id:"panel-rag-pipeline","aria-labelledby":"tab-rag-pipeline",className:"space-y-6","data-testid":"tab-content-rag-pipeline",children:[(0,c.jsx)(R.RAGPipelineGraphViewer,{pipelineConfig:u.pipelineConfig,circuitBreakerStatus:u.circuitBreakerStatus,stageMetrics:u.stageMetrics}),(0,c.jsx)(R.EnrichmentStrategyBoard,{strategies:u.enrichmentStrategies,featureFlags:u.featureFlags,isUpdating:e.state!=="idle",onToggleStage:(r,S,h)=>e.submit({intent:"update_enrichment_strategy",strategyId:String(r.id),domainId:String(r.domainId),stage:S,enabled:String(h)},{method:"post"})}),(0,c.jsx)(R.InfrastructureHealthMonitor,{health:u.systemHealth,isRefreshing:e.state!=="idle",onRefresh:()=>e.submit({intent:"refresh_health"},{method:"post"})})]}),g==="knowledge-graph"&&(0,c.jsxs)("div",{role:"tabpanel",id:"panel-knowledge-graph","aria-labelledby":"tab-knowledge-graph",className:"space-y-6","data-testid":"tab-content-knowledge-graph",children:[(0,c.jsx)(R.OntologyStatusCard,{tenantId:u.tenantId,ontologyStatus:u.ontologyStatus}),(0,c.jsx)(v.KnowledgeGraphExplorer,{topologyMaxLabels:F.GRAPH_INDEX_LIMITS.topologyLabels.default,schema:u.graphSchema,tenantId:u.tenantId,unresolvedEntities:u.unresolvedEntities,onTraverse:s,onBrowseLabel:i===void 0?void 0:d,nodeIndexPage:l,nodeIndexFailure:m,isNodeIndexLoading:y,onResolveEntity:(r,S)=>{e.submit({intent:"resolve_entity",entityId:r,action:S},{method:"post"})}})]}),g==="parameters"&&(0,c.jsxs)("div",{role:"tabpanel",id:"panel-parameters","aria-labelledby":"tab-parameters",className:"space-y-6","data-testid":"tab-content-parameters",children:[(0,c.jsxs)("div",{className:"grid grid-cols-1 gap-6 md:grid-cols-2",children:[(0,c.jsx)(v.FeatureFlagBoard,{flags:O,isUpdating:e.state!=="idle",onToggleFlag:(r,S)=>{e.submit({intent:"toggle_flag",flagKey:r,enabled:String(S)},{method:"post"})}}),(0,c.jsx)(v.ClassificationRuleEditor,{rules:u.classificationRules,consultedBy:u.classificationRuleConsumer,onReorderRules:r=>{e.submit({intent:"reorder_rules",orderedRuleIds:JSON.stringify(r)},{method:"post"})}})]}),u.policiesMissingDestination.length>0&&(0,c.jsxs)("div",{"data-testid":"policies-missing-destination",role:"alert",style:{padding:"10px 12px",borderRadius:"6px",backgroundColor:"#fef2f2",color:"#b91c1c",fontSize:"12px"},children:[(0,c.jsx)("strong",{children:"\u6B21\u306E\u533A\u5206\u30FB\u6A5F\u80FD\u306F\u5B9F\u884C\u6642\u306B\u5931\u6557\u3057\u307E\u3059\u3002"})," \u53C2\u7167\u3059\u308B\u30D7\u30ED\u30F3\u30D7\u30C8\u884C\u306B\u5B9B\u5148\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",(0,c.jsx)("ul",{style:{margin:"6px 0 0",paddingInlineStart:"18px"},children:u.policiesMissingDestination.map(r=>(0,c.jsxs)("li",{"data-testid":`missing-destination-${r.confidentialityLevel}-${r.capability}`,children:[r.confidentialityLevel," / ",r.capability," \u2192 ",r.promptKey," (",r.modelProvider,") \u306E ",(0,c.jsx)("code",{children:"extra_params.base_url"})]},`${r.confidentialityLevel}:${r.capability}`))}),(0,c.jsx)("span",{style:{display:"block",marginTop:"4px",fontSize:"11px"},children:"\u5B9B\u5148\u3092\u8A2D\u5B9A\u3057\u3066\u3082\u3001\u305D\u306E\u30DB\u30B9\u30C8\u304C\u914D\u5099\u5185\u3068\u3057\u3066\u767B\u9332\u3055\u308C\u3066\u3044\u306A\u3051\u308C\u3070\u62D2\u5426\u3055\u308C\u307E\u3059\u3002"})]}),(0,c.jsx)(v.ConfidentialityPolicyBoard,{policies:u.confidentialityPolicies,promptKeys:u.promptTemplates.map(r=>r.template_key),isUpdating:e.state!=="idle",onChangePolicy:r=>{e.submit({intent:"update_confidentiality_policy",confidentialityLevel:r.confidentialityLevel,capability:r.capability,isEnabled:String(r.isEnabled),allowCloudProvider:String(r.allowCloudProvider),promptKey:r.promptKey??""},{method:"post"})}}),(0,c.jsx)(v.TranscriptionAdaptationBoard,{vocabulary:u.transcriptionVocabulary,references:u.transcriptionReferences,unresolvedUris:u.unresolvedReferenceUris,isUpdating:e.state!=="idle",onSaveTerm:r=>{e.submit({intent:"save_transcription_term",id:r.id===null?"":String(r.id),term:r.term,reading:r.reading??"",boost:r.boost===null?"":String(r.boost),domainKey:r.domainKey??"",isActive:String(r.isActive)},{method:"post"})},onSaveReference:r=>{e.submit({intent:"save_transcription_reference",id:r.id===null?"":String(r.id),fileUri:r.fileUri,domainKey:r.domainKey??"",isActive:String(r.isActive)},{method:"post"})}}),(0,c.jsx)(v.SystemParameterTable,{parameters:u.systemParameters,onSaveParameter:(r,S)=>{e.submit({intent:"update_parameter",paramKey:r,paramValue:String(S)},{method:"post"})}})]}),g==="prompts"&&(0,c.jsxs)("div",{role:"tabpanel",id:"panel-prompts","aria-labelledby":"tab-prompts",className:"space-y-6","data-testid":"tab-content-prompts",children:[(0,c.jsx)(v.PromptTemplateConsole,{templates:u.promptTemplates,isSaving:e.state!=="idle",onSaveTemplate:r=>{e.submit({intent:"update_prompt",templateKey:r.template_key,payload:JSON.stringify({templateText:r.template_text,modelName:r.model_name,temperature:r.temperature,maxOutputTokens:r.max_output_tokens,responseSchema:r.response_schema,endpointBaseUrl:r.endpoint_base_url??null})},{method:"post"})}}),(0,c.jsx)(v.GovernanceDryRunConsole,{onSimulate:n})]}),g==="data-retention"&&(0,c.jsxs)("div",{role:"tabpanel",id:"panel-data-retention","aria-labelledby":"tab-data-retention",className:"space-y-6","data-testid":"tab-content-data-retention",children:[(0,c.jsx)(v.TriStoreIntegrityAudit,{auditData:u.triStoreAuditData,onTriggerReconcile:()=>{e.submit({intent:"reconcile"},{method:"post"})}}),(0,c.jsxs)("div",{className:"grid grid-cols-1 gap-6 md:grid-cols-2",children:[(0,c.jsx)(R.SyncStatusMonitor,{counts:u.syncCounts,totalFiles:u.totalFiles,failedItems:u.failedSyncItems,onRetryItem:r=>{e.submit({intent:"retry_job",fileId:String(r)},{method:"post"})},onRetryAll:()=>{e.submit({intent:"retry_all_failed"},{method:"post"})}}),(0,c.jsx)(R.QdrantStorageCard,{collections:u.qdrantCollections.collections,probeFailure:u.qdrantCollections.probe_failure,health:{healthy:u.systemHealth.services.qdrant.status==="connected",latency_ms:u.systemHealth.services.qdrant.latencyMs}})]})]})]})]})}var Ie=new Set(F.EnrichmentSyncStatusSchema.options.filter(t=>t!=="SYNCED"&&!t.startsWith("FAILED"))),Z=2e3;function we(t,e,o){let[s,i]=(0,T.useState)(null),n=(0,T.useRef)(e);n.current=e;let a=(0,T.useRef)(t);a.current!==t&&(a.current=t,s!==null&&i(null));let l=s??t,p=l?.some(m=>Ie.has(m.syncStatus))===!0;return(0,T.useEffect)(()=>{if(!(o&&p&&n.current))return;let m=!1,f,y=async()=>{let b=n.current;if(!(m||!b)){try{let d=await b();if(m)return;i(d)}catch{if(m)return}f=setTimeout(y,Z)}};return f=setTimeout(y,Z),()=>{m=!0,f!==void 0&&clearTimeout(f)}},[p,o]),l}function Te(t){let e=(0,j.useLoaderData)(),o=(0,j.useFetcher)(),s=t.data??e,i=t.fetcher??o;return s?(0,c.jsx)(ee,{data:s,fetcher:i,onRefreshIngestQueue:t.onRefreshIngestQueue,renderHeader:t.renderHeader,onTraverseGraph:t.onTraverseGraph,onBrowseGraphNodes:t.onBrowseGraphNodes,onSimulateGovernance:t.onSimulateGovernance}):(0,c.jsx)("div",{className:"p-8 text-center text-slate-500","data-testid":"storage-admin-loading",children:"\u30C7\u30FC\u30BF\u8AAD\u307F\u8FBC\u307F\u4E2D..."})}function $(t={}){return t.data?(0,c.jsx)(ee,{data:t.data,fetcher:t.fetcher??Re,renderHeader:t.renderHeader,onTraverseGraph:t.onTraverseGraph,onBrowseGraphNodes:t.onBrowseGraphNodes,onSimulateGovernance:t.onSimulateGovernance}):(0,c.jsx)(Te,{...t})}var Y=require("@aiquants/authz-core"),ce=require("@aiquants/enrichment-core"),C=require("@aiquants/governance-core");function A(t){if(typeof globalThis<"u"&&"process"in globalThis)return globalThis.process?.env?.[t]}function H(t,e){let o=t?.trim();if(!o)throw new Error(`${e} is not configured; this probe will not guess an endpoint to send credentials to.`);return o}function te(t,e,o){let s=t??(e?.trim()?Number(e):Number.NaN);if(!Number.isInteger(s)||s<=0||s>65535)throw new Error(`${o} is not configured with a valid port; this probe will not guess one.`);return s}function ne(t,e){if(t!==void 0)return t;let o=e?.trim().toLowerCase();if(!(o===void 0||o===""))return o==="1"||o==="true"||o==="yes"||o==="on"}function re(t){let e=t.trim().split("://",1)[0]?.toLowerCase();if(e&&t.includes("://"))return e.endsWith("s")||e.includes("+s")}function Pe(t){let o=(t.split("://").pop()??"").split("/",1)[0]??"",s=o.split(":").pop();if(!s||s===o)return;let i=Number(s);return Number.isInteger(i)&&i>0&&i<=65535?i:void 0}async function V(t,e){let o;try{return await Promise.race([t,new Promise((s,i)=>{o=setTimeout(()=>i(new Error(`Probe timed out after ${e}ms`)),e)})])}finally{o!==void 0&&clearTimeout(o)}}async function se(t){let e=t?.qdrantApiKey??A("QDRANT_API_KEY")??"",o=t?.timeoutMs??3e3,s=Date.now(),i="";try{i=H(t?.qdrantUrl??A("QDRANT_URL"),"QDRANT_URL");let n={};e&&(n["api-key"]=e);let[a,l]=await Promise.all([fetch(`${i}/`,{headers:n,signal:AbortSignal.timeout(o)}),fetch(`${i}/collections`,{headers:n,signal:AbortSignal.timeout(o)})]);if(!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);if(!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText} (/collections)`);let p=await a.json(),m=Date.now()-s,y=(await l.json()).result?.collections?.length??0;return{serviceName:"Qdrant",category:"vector",status:"connected",version:p.version??"unknown",endpoint:i,latencyMs:m,details:{engine:p.title??"qdrant",collectionsCount:y,restPort:Pe(i)??null,tls:re(i)??null}}}catch(n){let a=Date.now()-s,l=n instanceof Error?n.message:String(n);return{serviceName:"Qdrant",category:"vector",status:"error",version:null,endpoint:i,latencyMs:a,details:{},errorMessage:l}}}async function ie(t){let e=t?.timeoutMs??3e3,o=Date.now(),s=t?.neo4jBoltUri??A("NEO4J_URI")??"";try{let i=t?.graphReader;if(!i)throw new Error("Graph reader not configured");let n=t?.tenantId,[a,l]=await Promise.all([V(i("CALL dbms.components() YIELD versions, edition RETURN versions[0] AS version, edition",{}),e),V(n?i("MATCH (n {tenantId: $tenantId}) RETURN count(n) AS node_count",{tenantId:n}):i("RETURN null AS node_count",{}),e)]);if(!a.ok)throw new Error(a.reason);if(!l.ok)throw new Error(l.reason);let[p,m]=a.rows[0]??[],f=l.rows[0]?.[0],y=Date.now()-o;return{serviceName:"Neo4j",category:"graph",status:"connected",version:typeof p=="string"?p:"unknown",endpoint:s,latencyMs:y,details:{edition:typeof m=="string"?m:"unknown",boltUri:s,nodeCount:typeof f=="number"?f:null,tls:re(s)??null}}}catch(i){let n=Date.now()-o,a=i instanceof Error?i.message:String(i);return{serviceName:"Neo4j",category:"graph",status:"error",version:null,endpoint:s,latencyMs:n,details:{},errorMessage:a}}}async function ae(t){let e=Date.now(),o="",s=ne(t?.redisTls,A("REDIS_TLS")),i=Number.NaN;try{let n=t?.redisClient;if(!n)throw new Error("Redis client not configured");let a=H(t?.redisHost??A("REDIS_HOST"),"REDIS_HOST");i=te(t?.redisPort,A("REDIS_PORT"),"REDIS_PORT"),o=`${s===!1?"redis":"rediss"}://${a}:${i}`,await n.ping();let p=(await n.info("server")).match(/redis_version:([^\r\n]+)/),m=p?p[1]:"unknown",f=null;if(typeof n.dbSize=="function")try{f=await n.dbSize()}catch{f=null}let y=Date.now()-e;return{serviceName:"Redis",category:"cache",status:"connected",version:m,endpoint:o,latencyMs:y,details:{totalKeys:f,port:i,tls:s??null,database:0}}}catch(n){let a=Date.now()-e,l=n instanceof Error?n.message:String(n);return{serviceName:"Redis",category:"cache",status:"error",version:null,endpoint:o,latencyMs:a,details:{},errorMessage:l}}}async function oe(t){let e=Date.now(),o="",s=ne(t?.sqlServerTls,A("SQL_SERVER_TLS")),i=Number.NaN;try{let n=t?.sqlServerExecute;if(!n)throw new Error("SQL Server executor not configured");let a=H(t?.sqlServerHost??A("SQL_SERVER_HOST"),"SQL_SERVER_HOST");i=te(t?.sqlServerPort,A("SQL_SERVER_PORT"),"SQL_SERVER_PORT"),o=`${a}:${i}`;let l=await n(),p=l.version??"unknown",m=typeof l.db_name=="string"&&l.db_name!==""?l.db_name:null,f=p.split(`
|
|
2
|
+
`)[0]??p,y=f.match(/Microsoft SQL Server \d+ \([^)]+\)/),b=y?y[0].replace("Microsoft SQL Server ",""):f.substring(0,30),d=Date.now()-e;return{serviceName:"SQL Server",category:"database",status:"connected",version:b,endpoint:o,latencyMs:d,details:{database:m,port:i,tls:s??null,fullVersion:f}}}catch(n){let a=Date.now()-e,l=n instanceof Error?n.message:String(n);return{serviceName:"SQL Server",category:"database",status:"error",version:null,endpoint:o,latencyMs:a,details:{},errorMessage:l}}}async function le(t){let e=t?.timeoutMs??3e3,o=Date.now(),s="";try{s=H(t?.backendApiHost??A("BACKEND_API_HOST"),"BACKEND_API_HOST");let i=await fetch(`${s}/openapi.json`,{signal:AbortSignal.timeout(e)});if(!i.ok)throw new Error(`HTTP ${i.status}: ${i.statusText}`);let n=await i.json(),a=Object.keys(n.paths??{}).length,l=Date.now()-o;return{serviceName:"AI Quant API",category:"api",status:"connected",version:typeof n.info?.version=="string"&&n.info.version!==""?n.info.version:null,endpoint:s,latencyMs:l,details:{title:n.info?.title??"AI Quant API",endpointsCount:a}}}catch(i){let n=Date.now()-o,a=i instanceof Error?i.message:String(i);return{serviceName:"AI Quant API",category:"api",status:"error",version:null,endpoint:s,latencyMs:n,details:{},errorMessage:a}}}async function J(t){let[e,o,s,i,n]=await Promise.all([se(t),ie(t),ae(t),oe(t),le(t)]),a=e.status==="connected"&&o.status==="connected"&&s.status==="connected"&&i.status==="connected"&&n.status==="connected";return{services:{qdrant:e,neo4j:o,redis:s,sqlServer:i,quantsApi:n},allHealthy:a,checkedAt:new Date().toISOString()}}function W(t){let{store:e,healthProbeOptions:o,resourceKey:s="storage_admin",requireUser:i,requirePermission:n,resolveTenantId:a,authorizeIngest:l}=t;async function p(y){return a?await a(y):"default"}async function m(y){let{request:b}=y;if(i&&!await i(b))throw new Response("\u8A8D\u8A3C\u304C\u5FC5\u8981\u3067\u3059\u3002",{status:401});if(n)try{await n(b,{resourceKey:s,action:"read"})}catch(B){throw B instanceof Y.AuthzDeniedError?new Response("\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093\u3002",{status:403}):B}let d=await p(b),[k,E,P]=await Promise.all([e.getFeatureFlags(d),e.getSystemParameters(d),e.getSyncCounts(d)]),g={featureFlags:k,systemParameters:E,syncCounts:P},[N,x,u,w,I,O,D,K,q,G,r,S,h,_,U,ue,de]=await Promise.all([e.getConfidentialityPolicies(d),e.getTranscriptionVocabulary(d),e.getTranscriptionReferences(d),e.getUnresolvedReferenceUris(d),e.getPoliciesMissingDestination(d),e.getPromptTemplates(d),e.getClassificationRules(d),e.getFailedSyncItems(d),e.getGraphSchema(d),e.getTriStoreAuditData(d,g),e.getUnresolvedEntities(d),e.getQdrantCollections(d),J({...o,tenantId:d}),e.getPipelineConfig(d,g),e.getRecentIngestItems(d),e.getOntologyStatus(d,g),e.getEnrichmentStrategies(d)]),pe=e.getCircuitBreakerStatus(),me=e.getStageMetrics();return{tenantId:d,featureFlags:g.featureFlags,confidentialityPolicies:N,transcriptionVocabulary:x,transcriptionReferences:u,unresolvedReferenceUris:w,policiesMissingDestination:I,systemParameters:g.systemParameters,promptTemplates:O,classificationRules:D,classificationRuleConsumer:e.classificationRuleConsumer??null,syncCounts:g.syncCounts.counts,totalFiles:g.syncCounts.total,failedSyncItems:K,circuitBreakerStatus:pe,pipelineConfig:_,stageMetrics:me,graphSchema:q,enrichmentStrategies:de,triStoreAuditData:G,unresolvedEntities:r,qdrantCollections:S,systemHealth:h,recentIngestItems:U,ontologyStatus:ue}}async function f(y){let{request:b}=y,d=null,k;if(i){let w=await i(b);if(!w)return Response.json({error:"\u8A8D\u8A3C\u304C\u5FC5\u8981\u3067\u3059\u3002"},{status:401});let I=w;d=I.email||I.id||I.name||null,typeof I.accessToken=="string"&&I.accessToken!=="mock-access-token"&&(k=I.accessToken)}if(!d)return Response.json({error:"\u64CD\u4F5C\u8005\u3092\u7279\u5B9A\u3067\u304D\u306A\u3044\u305F\u3081\u8A2D\u5B9A\u3092\u5909\u66F4\u3067\u304D\u307E\u305B\u3093\u3002"},{status:403});if(n)try{await n(b,{resourceKey:s,action:"update"})}catch(w){if(w instanceof Y.AuthzDeniedError)return Response.json({error:"\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093\u3002"},{status:403});throw w}let E=await p(b),P=await b.formData(),g=String(P.get("intent")??"");if(g==="refresh_health")return Response.json({success:!0,refreshed:!0});let N=await Ae(e,E,g,P,d);if(N)return N;let x=await Ee(e,E,g,P,d,k);if(x)return x;if(g==="resolve_entity"){let w=String(P.get("entityId")??""),I=String(P.get("action")??"");return!w||I!=="merge"&&I!=="promote"?Response.json({error:"Valid entityId and action ('merge' | 'promote') are required"},{status:400}):(await e.resolveEntity(E,w,I),Response.json({success:!0,entityId:w,action:I}))}let u=await xe(e,E,g,P,d,b,l,k);return u||Response.json({error:`Unknown intent: ${g}`},{status:400})}return{loader:m,action:f}}function z(t){let e=String(t??"").trim();return e===""?null:e}function M(t){let e=String(t??"").trim();if(e==="")return null;let o=Number(e);if(!(!Number.isSafeInteger(o)||o<=0))return o}function _e(t){let e=String(t??"").trim();if(e==="")return null;let o=Number(e);if(!(!Number.isFinite(o)||o<=0))return o}async function Ae(t,e,o,s,i){if(o==="update_enrichment_strategy"){let n=String(s.get("stage")??"");if(!(0,ce.isEnrichmentStageKey)(n))return Response.json({error:"stage must be a canonical enrichment stage key"},{status:400});let a=M(s.get("strategyId")),l=M(s.get("domainId"));if(a==null||l===void 0||l===null)return Response.json({error:"strategyId and domainId must be positive integers naming existing rows"},{status:400});let p=String(s.get("enabled")??"")==="true";try{await t.updateEnrichmentStrategy(e,{strategyId:a,domainId:l,stage:n,enabled:p},i)}catch(m){return Response.json({error:m instanceof Error?m.message:"\u53D6\u308A\u8FBC\u307F\u6226\u7565\u3092\u66F4\u65B0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002"},{status:400})}return Response.json({success:!0,strategyId:a,domainId:l,stage:n,enabled:p})}if(o==="toggle_flag"){let n=String(s.get("flagKey")??""),a=String(s.get("enabled")??"")==="true";return n?(await t.toggleFeatureFlag(e,n,a,i),Response.json({success:!0,flagKey:n,enabled:a})):Response.json({error:"flagKey is required"},{status:400})}if(o==="update_confidentiality_policy"){let n=String(s.get("confidentialityLevel")??""),a=String(s.get("capability")??"");if(!(C.ConfidentialityLevelSchema.safeParse(n).success&&C.GovernedCapabilitySchema.safeParse(a).success))return Response.json({error:"confidentialityLevel and capability must be canonical values"},{status:400});let l=String(s.get("allowCloudProvider")??"")==="true";if(l&&!C.CLOUD_CAPABLE_CAPABILITIES.includes(a))return Response.json({error:`${a} sends nothing outside the deployment, so it has no cloud permission to grant`},{status:400});let p=String(s.get("promptKey")??"");return await t.updateConfidentialityPolicy(e,{confidentialityLevel:n,capability:a,isEnabled:String(s.get("isEnabled")??"")==="true",allowCloudProvider:l,promptKey:p===""?null:p},i),Response.json({success:!0,confidentialityLevel:n,capability:a})}if(o==="save_transcription_term"){let n=String(s.get("term")??"").trim();if(!n)return Response.json({error:"term is required"},{status:400});let a=_e(s.get("boost"));if(a===void 0)return Response.json({error:"boost must be a number greater than zero, or absent to let the service decide"},{status:400});let l=M(s.get("id"));return l===void 0?Response.json({error:"id must be a positive integer naming an existing row, or absent for a new one"},{status:400}):(await t.saveTranscriptionTerm(e,{id:l,term:n,reading:z(s.get("reading")),boost:a,domainKey:z(s.get("domainKey")),isActive:String(s.get("isActive")??"true")==="true"},i),Response.json({success:!0,term:n}))}if(o==="save_transcription_reference"){let n=String(s.get("fileUri")??"").trim();if(!n)return Response.json({error:"fileUri is required"},{status:400});let a=M(s.get("id"));return a===void 0?Response.json({error:"id must be a positive integer naming an existing row, or absent for a new one"},{status:400}):(await t.saveTranscriptionReference(e,{id:a,fileUri:n,domainKey:z(s.get("domainKey")),isActive:String(s.get("isActive")??"true")==="true"},i),Response.json({success:!0,fileUri:n}))}if(o==="update_parameter"){let n=String(s.get("paramKey")??""),a=String(s.get("paramValue")??"");return n?(await t.updateSystemParameter(e,n,a,i),Response.json({success:!0,paramKey:n,paramValue:a})):Response.json({error:"paramKey is required"},{status:400})}if(o==="update_prompt"){let n=String(s.get("templateKey")??""),a=String(s.get("payload")??"{}"),l={templateText:"",modelName:"",temperature:0,maxOutputTokens:0,endpointBaseUrl:null};try{l=JSON.parse(a)}catch{return Response.json({error:"Invalid JSON payload"},{status:400})}if(!n)return Response.json({error:"templateKey is required"},{status:400});try{return await t.updatePromptTemplate(e,n,l,i),Response.json({success:!0,templateKey:n})}catch(p){return Response.json({error:p instanceof Error?p.message:String(p)},{status:400})}}if(o==="reorder_rules"){let n=String(s.get("orderedRuleIds")??"[]"),a=[];try{a=JSON.parse(n)}catch{return Response.json({error:"Invalid orderedRuleIds JSON"},{status:400})}return await t.reorderClassificationRules(e,a,i),Response.json({success:!0,orderedRuleIds:a})}return null}async function Ee(t,e,o,s,i,n){if(o==="retry_job"){let a=String(s.get("fileId")??"");if(!a)return Response.json({error:"fileId is required"},{status:400});try{return await t.retrySyncItem(e,a,i,n),Response.json({success:!0,fileId:a})}catch(l){return Response.json({error:l instanceof Error?l.message:String(l)},{status:400})}}if(o==="retry_all_failed")try{return await t.retryAllFailedSyncItems(e,i,n),Response.json({success:!0,reconciled:!0})}catch(a){return Response.json({error:a instanceof Error?a.message:String(a)},{status:400})}if(o==="reconcile")try{let a=await t.reconcileTriStore(e,n);return Response.json({success:!0,reconciled:!0,result:a})}catch(a){return Response.json({error:a instanceof Error?a.message:String(a)},{status:400})}return null}function Ne(t){if(typeof t!="object"||t===null)return"payload must be an object";let e=t;if(typeof e.fileUri!="string"||e.fileUri.trim()==="")return"payload.fileUri is required";if(!C.ConfidentialityLevelSchema.safeParse(e.confidentialityLevel).success)return`payload.confidentialityLevel must be one of ${C.ConfidentialityLevelSchema.options.join(", ")}`;let s=e.departmentId;return s!=null&&(typeof s!="number"||!Number.isInteger(s))?"payload.departmentId must be an integer or null":null}async function xe(t,e,o,s,i,n,a,l){if(o==="ingest_document"){let p=String(s.get("payload")??"");if(!p)return Response.json({error:"payload is required"},{status:400});let m;try{m=JSON.parse(p)}catch{return Response.json({error:"Invalid JSON payload"},{status:400})}let f=Ne(m);if(f)return Response.json({error:f},{status:400});let y=m,b=await a(n,y);if(b!==null)return Response.json({error:b},{status:403});try{let d=l?await t.ingestDocument(e,y,i,l):await t.ingestDocument(e,y,i);return Response.json({success:!0,result:d})}catch(d){return Response.json({error:d instanceof Error?d.message:String(d)},{status:400})}}if(o==="inspect_uri"){let p=String(s.get("fileUri")??"").trim();if(!p)return Response.json({error:"fileUri is required"},{status:400});if(!t.inspectFileUri)return Response.json({error:"inspectFileUri is not implemented"},{status:501});try{let m=l?await t.inspectFileUri(e,p,l):await t.inspectFileUri(e,p);return Response.json({success:!0,inspection:m})}catch(m){return Response.json({error:m instanceof Error?m.message:String(m)},{status:400})}}return null}function Ce(t){let e=W(t);return{loader:e.loader,action:e.action,View:$,server:e}}0&&(module.exports={StorageAdminConsoleView,checkAllSystemHealth,checkBackendApiHealth,checkNeo4jHealth,checkQdrantHealth,checkRedisHealth,checkSqlServerHealth,createStorageAdminApp,createStorageAdminServer});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { EnrichmentStageKey } from "@aiquants/enrichment-core";
|
|
2
|
+
export { SearchMode } from "@aiquants/enrichment-core";
|
|
3
|
+
import { EnrichmentStrategyRow, FailedSyncItem, QdrantStorageOverview, CircuitBreakerState, PipelineConfig, DocumentIngestPayload, FileInspectionResult, RecentIngestItem, OntologyStatusData } from "@aiquants/enrichment-react";
|
|
4
|
+
export { DocumentIngestLabel, DocumentIngestPayload, EnrichmentStrategyRow, FailedSyncItem, FileInspectionResult, FusionStrategy, MetadataSearchHit, MetadataSearchParams, MetadataSearchResult, OntologyStatusData, PipelineConfig, QdrantCollectionInfo, QdrantStorageOverview, RecentIngestItem, SearchHitGraphRelation, SearchHitScoreBreakdown, StrategyProvenance } from "@aiquants/enrichment-react";
|
|
5
|
+
import { ConfidentialityPolicyRow, TranscriptionTermRow, TranscriptionReferenceRow, PromptTemplateItem, ClassificationRuleItem, GraphSchemaStats, TriStoreAuditData, TriStoreReconcileResult, GraphTraversalRunner, GraphNodeIndexOutcome, SimulationRunner } from "@aiquants/governance-react";
|
|
6
|
+
export { ClassificationRuleItem as ClassificationRule, GraphNodeIndexOutcome, GraphNodeIndexPage, GraphNodeSummary, GraphSchemaStats, GraphTraversalInput, GraphTraversalOutcome, GraphTraversalRunner, PromptTemplateItem, SimulationOutcome, SimulationRunInput, SimulationRunResult, SimulationRunner, SimulationScoreSet, SimulationVerdictFlip, TriStoreAuditData, TriStoreReconcileResult } from "@aiquants/governance-react";
|
|
7
|
+
import * as react from "react";
|
|
8
|
+
import { ReactNode } from "react";
|
|
9
|
+
import { useFetcher } from "react-router";
|
|
10
|
+
interface DocumentIngestResult {
|
|
11
|
+
metadataId: number;
|
|
12
|
+
revision: number;
|
|
13
|
+
createdNew: boolean;
|
|
14
|
+
jobId: string;
|
|
15
|
+
}
|
|
16
|
+
interface ServiceHealthStatus {
|
|
17
|
+
serviceName: string;
|
|
18
|
+
category: "vector" | "graph" | "cache" | "database" | "api";
|
|
19
|
+
status: "connected" | "error";
|
|
20
|
+
version: string | null;
|
|
21
|
+
endpoint: string;
|
|
22
|
+
latencyMs: number;
|
|
23
|
+
details: Record<string, string | number | boolean | null>;
|
|
24
|
+
errorMessage?: string;
|
|
25
|
+
}
|
|
26
|
+
interface SystemInfrastructureHealth {
|
|
27
|
+
services: {
|
|
28
|
+
qdrant: ServiceHealthStatus;
|
|
29
|
+
neo4j: ServiceHealthStatus;
|
|
30
|
+
redis: ServiceHealthStatus;
|
|
31
|
+
sqlServer: ServiceHealthStatus;
|
|
32
|
+
quantsApi: ServiceHealthStatus;
|
|
33
|
+
};
|
|
34
|
+
allHealthy: boolean;
|
|
35
|
+
checkedAt: string;
|
|
36
|
+
}
|
|
37
|
+
interface SystemParameter {
|
|
38
|
+
key: string;
|
|
39
|
+
value: string;
|
|
40
|
+
category: string;
|
|
41
|
+
description: string;
|
|
42
|
+
data_type: "string" | "int" | "float" | "bool" | "json";
|
|
43
|
+
is_secret: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface PromptTemplateUpdate {
|
|
46
|
+
templateText: string;
|
|
47
|
+
modelName: string;
|
|
48
|
+
temperature: number;
|
|
49
|
+
maxOutputTokens: number;
|
|
50
|
+
responseSchema?: Record<string, unknown> | string | null;
|
|
51
|
+
endpointBaseUrl: string | null;
|
|
52
|
+
}
|
|
53
|
+
interface PolicyWithoutDestination {
|
|
54
|
+
confidentialityLevel: string;
|
|
55
|
+
capability: string;
|
|
56
|
+
promptKey: string;
|
|
57
|
+
modelProvider: string;
|
|
58
|
+
}
|
|
59
|
+
interface UnresolvedEntity {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
category: string;
|
|
63
|
+
occurrences: number;
|
|
64
|
+
co_occurrences: number;
|
|
65
|
+
suggested_action: "merge" | "promote";
|
|
66
|
+
}
|
|
67
|
+
type StageMetrics = Record<string, {
|
|
68
|
+
latency_p50_ms: number;
|
|
69
|
+
latency_p95_ms: number;
|
|
70
|
+
throughput_rps: number;
|
|
71
|
+
success_rate: number;
|
|
72
|
+
}>;
|
|
73
|
+
interface StorageAdminLoaderData {
|
|
74
|
+
tenantId: string;
|
|
75
|
+
featureFlags: Record<string, boolean>;
|
|
76
|
+
systemParameters: SystemParameter[];
|
|
77
|
+
promptTemplates: PromptTemplateItem[];
|
|
78
|
+
classificationRules: ClassificationRuleItem[];
|
|
79
|
+
classificationRuleConsumer: string | null;
|
|
80
|
+
syncCounts: Record<string, number>;
|
|
81
|
+
totalFiles: number;
|
|
82
|
+
failedSyncItems: FailedSyncItem[];
|
|
83
|
+
circuitBreakerStatus: Record<string, CircuitBreakerState>;
|
|
84
|
+
pipelineConfig: PipelineConfig;
|
|
85
|
+
stageMetrics: StageMetrics;
|
|
86
|
+
graphSchema: GraphSchemaStats;
|
|
87
|
+
enrichmentStrategies: EnrichmentStrategyRow[];
|
|
88
|
+
triStoreAuditData: TriStoreAuditData;
|
|
89
|
+
unresolvedEntities: UnresolvedEntity[];
|
|
90
|
+
qdrantCollections: QdrantStorageOverview;
|
|
91
|
+
systemHealth: SystemInfrastructureHealth;
|
|
92
|
+
recentIngestItems?: RecentIngestItem[];
|
|
93
|
+
ontologyStatus: OntologyStatusData;
|
|
94
|
+
confidentialityPolicies: ConfidentialityPolicyRow[];
|
|
95
|
+
transcriptionVocabulary: TranscriptionTermRow[];
|
|
96
|
+
transcriptionReferences: TranscriptionReferenceRow[];
|
|
97
|
+
unresolvedReferenceUris: string[];
|
|
98
|
+
policiesMissingDestination: PolicyWithoutDestination[];
|
|
99
|
+
}
|
|
100
|
+
interface EnrichmentStrategyUpdate {
|
|
101
|
+
strategyId: number;
|
|
102
|
+
domainId: number;
|
|
103
|
+
stage: EnrichmentStageKey;
|
|
104
|
+
enabled: boolean;
|
|
105
|
+
}
|
|
106
|
+
interface ConsoleConfigSnapshot {
|
|
107
|
+
readonly featureFlags: Record<string, boolean>;
|
|
108
|
+
readonly systemParameters: SystemParameter[];
|
|
109
|
+
readonly syncCounts: {
|
|
110
|
+
counts: Record<string, number>;
|
|
111
|
+
total: number;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
interface StorageAdminStore {
|
|
115
|
+
getFeatureFlags(tenantId: string): Promise<Record<string, boolean>>;
|
|
116
|
+
getEnrichmentStrategies(tenantId: string): Promise<EnrichmentStrategyRow[]>;
|
|
117
|
+
updateEnrichmentStrategy(tenantId: string, input: EnrichmentStrategyUpdate, actor: string): Promise<void>;
|
|
118
|
+
toggleFeatureFlag(tenantId: string, flagKey: string, enabled: boolean, actor: string): Promise<void>;
|
|
119
|
+
getSystemParameters(tenantId: string): Promise<SystemParameter[]>;
|
|
120
|
+
updateSystemParameter(tenantId: string, paramKey: string, paramValue: string, actor: string): Promise<void>;
|
|
121
|
+
getConfidentialityPolicies(tenantId: string): Promise<ConfidentialityPolicyRow[]>;
|
|
122
|
+
updateConfidentialityPolicy(tenantId: string, policy: ConfidentialityPolicyRow, actor: string): Promise<void>;
|
|
123
|
+
getTranscriptionVocabulary(tenantId: string): Promise<TranscriptionTermRow[]>;
|
|
124
|
+
saveTranscriptionTerm(tenantId: string, row: Omit<TranscriptionTermRow, "id"> & {
|
|
125
|
+
id: number | null;
|
|
126
|
+
}, actor: string): Promise<void>;
|
|
127
|
+
getTranscriptionReferences(tenantId: string): Promise<TranscriptionReferenceRow[]>;
|
|
128
|
+
saveTranscriptionReference(tenantId: string, row: Omit<TranscriptionReferenceRow, "id"> & {
|
|
129
|
+
id: number | null;
|
|
130
|
+
}, actor: string): Promise<void>;
|
|
131
|
+
getUnresolvedReferenceUris(tenantId: string): Promise<string[]>;
|
|
132
|
+
getPoliciesMissingDestination(tenantId: string): Promise<PolicyWithoutDestination[]>;
|
|
133
|
+
getPromptTemplates(tenantId: string): Promise<PromptTemplateItem[]>;
|
|
134
|
+
updatePromptTemplate(tenantId: string, templateKey: string, payload: PromptTemplateUpdate, actor: string): Promise<void>;
|
|
135
|
+
getClassificationRules(tenantId: string): Promise<ClassificationRuleItem[]>;
|
|
136
|
+
classificationRuleConsumer?: string;
|
|
137
|
+
reorderClassificationRules(tenantId: string, orderedRuleIds: number[], actor: string): Promise<void>;
|
|
138
|
+
getSyncCounts(tenantId: string): Promise<{
|
|
139
|
+
counts: Record<string, number>;
|
|
140
|
+
total: number;
|
|
141
|
+
}>;
|
|
142
|
+
getFailedSyncItems(tenantId: string): Promise<FailedSyncItem[]>;
|
|
143
|
+
retrySyncItem(tenantId: string, fileId: string, actor?: string, accessToken?: string): Promise<void>;
|
|
144
|
+
retryAllFailedSyncItems(tenantId: string, actor?: string, accessToken?: string): Promise<void>;
|
|
145
|
+
getGraphSchema(tenantId: string): Promise<GraphSchemaStats>;
|
|
146
|
+
getTriStoreAuditData(tenantId: string, snapshot: ConsoleConfigSnapshot): Promise<TriStoreAuditData>;
|
|
147
|
+
reconcileTriStore(tenantId: string, accessToken?: string): Promise<TriStoreReconcileResult>;
|
|
148
|
+
getUnresolvedEntities(tenantId: string): Promise<UnresolvedEntity[]>;
|
|
149
|
+
resolveEntity(tenantId: string, entityId: string, action: "merge" | "promote"): Promise<void>;
|
|
150
|
+
getQdrantCollections(tenantId: string): Promise<QdrantStorageOverview>;
|
|
151
|
+
getCircuitBreakerStatus(): Record<string, CircuitBreakerState>;
|
|
152
|
+
getPipelineConfig(tenantId: string, snapshot: ConsoleConfigSnapshot): Promise<PipelineConfig>;
|
|
153
|
+
getStageMetrics(): StageMetrics;
|
|
154
|
+
ingestDocument(tenantId: string, payload: DocumentIngestPayload, actor: string, accessToken?: string): Promise<DocumentIngestResult>;
|
|
155
|
+
inspectFileUri?(tenantId: string, fileUri: string, accessToken?: string): Promise<FileInspectionResult>;
|
|
156
|
+
getRecentIngestItems(tenantId: string): Promise<RecentIngestItem[]>;
|
|
157
|
+
getOntologyStatus(tenantId: string, snapshot: ConsoleConfigSnapshot): Promise<OntologyStatusData>;
|
|
158
|
+
}
|
|
159
|
+
type GraphReadOutcome = {
|
|
160
|
+
readonly ok: true;
|
|
161
|
+
readonly rows: readonly (readonly unknown[])[];
|
|
162
|
+
} | {
|
|
163
|
+
readonly ok: false;
|
|
164
|
+
readonly reason: string;
|
|
165
|
+
};
|
|
166
|
+
type GraphReader = (statement: string, parameters: Record<string, unknown>) => Promise<GraphReadOutcome>;
|
|
167
|
+
interface HealthProbeOptions {
|
|
168
|
+
qdrantUrl?: string;
|
|
169
|
+
qdrantApiKey?: string;
|
|
170
|
+
graphReader?: GraphReader | null;
|
|
171
|
+
neo4jBoltUri?: string;
|
|
172
|
+
redisClient?: {
|
|
173
|
+
ping: () => Promise<string>;
|
|
174
|
+
info: (section?: string) => Promise<string>;
|
|
175
|
+
dbSize?: () => Promise<number>;
|
|
176
|
+
} | null;
|
|
177
|
+
redisHost?: string;
|
|
178
|
+
redisPort?: number;
|
|
179
|
+
redisTls?: boolean;
|
|
180
|
+
sqlServerExecute?: () => Promise<{
|
|
181
|
+
version: string;
|
|
182
|
+
db_name: string;
|
|
183
|
+
}>;
|
|
184
|
+
sqlServerHost?: string;
|
|
185
|
+
sqlServerPort?: number;
|
|
186
|
+
sqlServerTls?: boolean;
|
|
187
|
+
backendApiHost?: string;
|
|
188
|
+
timeoutMs?: number;
|
|
189
|
+
tenantId?: string;
|
|
190
|
+
}
|
|
191
|
+
interface CreateStorageAdminAppOptions {
|
|
192
|
+
store: StorageAdminStore;
|
|
193
|
+
healthProbeOptions?: HealthProbeOptions;
|
|
194
|
+
resourceKey?: string;
|
|
195
|
+
basePath?: string;
|
|
196
|
+
requireUser?: (request: Request) => Promise<unknown>;
|
|
197
|
+
requirePermission?: (request: Request, query: {
|
|
198
|
+
resourceKey: string;
|
|
199
|
+
action: "read" | "update";
|
|
200
|
+
}) => Promise<unknown>;
|
|
201
|
+
resolveTenantId?: (request: Request) => Promise<string> | string;
|
|
202
|
+
authorizeIngest: (request: Request, payload: DocumentIngestPayload) => Promise<string | null>;
|
|
203
|
+
}
|
|
204
|
+
interface StorageAdminFetcher {
|
|
205
|
+
state: "idle" | "submitting" | "loading";
|
|
206
|
+
formData?: FormData | null;
|
|
207
|
+
data?: {
|
|
208
|
+
error?: string;
|
|
209
|
+
inspection?: FileInspectionResult;
|
|
210
|
+
result?: unknown;
|
|
211
|
+
} | null;
|
|
212
|
+
submit: ReturnType<typeof useFetcher>["submit"];
|
|
213
|
+
}
|
|
214
|
+
interface StorageAdminConsoleViewProps {
|
|
215
|
+
data?: StorageAdminLoaderData;
|
|
216
|
+
fetcher?: StorageAdminFetcher;
|
|
217
|
+
renderHeader?: (props: {
|
|
218
|
+
title: string;
|
|
219
|
+
tenantId: string;
|
|
220
|
+
}) => ReactNode;
|
|
221
|
+
onTraverseGraph?: GraphTraversalRunner;
|
|
222
|
+
onBrowseGraphNodes?: (label: string, pageIndex: number) => Promise<GraphNodeIndexOutcome>;
|
|
223
|
+
onSimulateGovernance?: SimulationRunner;
|
|
224
|
+
onRefreshIngestQueue?: IngestQueueRefresher;
|
|
225
|
+
}
|
|
226
|
+
type IngestQueueRefresher = () => Promise<readonly RecentIngestItem[]>;
|
|
227
|
+
declare function StorageAdminConsoleView(props?: StorageAdminConsoleViewProps): react.JSX.Element;
|
|
228
|
+
declare function createStorageAdminApp(options: CreateStorageAdminAppOptions): {
|
|
229
|
+
loader: (args: {
|
|
230
|
+
request: Request;
|
|
231
|
+
}) => Promise<StorageAdminLoaderData>;
|
|
232
|
+
action: (args: {
|
|
233
|
+
request: Request;
|
|
234
|
+
}) => Promise<Response>;
|
|
235
|
+
View: typeof StorageAdminConsoleView;
|
|
236
|
+
server: {
|
|
237
|
+
loader: (args: {
|
|
238
|
+
request: Request;
|
|
239
|
+
}) => Promise<StorageAdminLoaderData>;
|
|
240
|
+
action: (args: {
|
|
241
|
+
request: Request;
|
|
242
|
+
}) => Promise<Response>;
|
|
243
|
+
};
|
|
244
|
+
};
|
|
245
|
+
declare function checkQdrantHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
246
|
+
declare function checkNeo4jHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
247
|
+
declare function checkRedisHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
248
|
+
declare function checkSqlServerHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
249
|
+
declare function checkBackendApiHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
250
|
+
declare function checkAllSystemHealth(opts?: HealthProbeOptions): Promise<SystemInfrastructureHealth>;
|
|
251
|
+
declare function createStorageAdminServer(options: CreateStorageAdminAppOptions): {
|
|
252
|
+
loader: (args: {
|
|
253
|
+
request: Request;
|
|
254
|
+
}) => Promise<StorageAdminLoaderData>;
|
|
255
|
+
action: (args: {
|
|
256
|
+
request: Request;
|
|
257
|
+
}) => Promise<Response>;
|
|
258
|
+
};
|
|
259
|
+
export { type ConsoleConfigSnapshot, type CreateStorageAdminAppOptions, type DocumentIngestResult, type EnrichmentStrategyUpdate, type GraphReadOutcome, type GraphReader, type HealthProbeOptions, type IngestQueueRefresher, type PolicyWithoutDestination, type PromptTemplateUpdate, type ServiceHealthStatus, type StageMetrics, StorageAdminConsoleView, type StorageAdminConsoleViewProps, type StorageAdminFetcher, type StorageAdminLoaderData, type StorageAdminStore, type SystemInfrastructureHealth, type SystemParameter, type UnresolvedEntity, checkAllSystemHealth, checkBackendApiHealth, checkNeo4jHealth, checkQdrantHealth, checkRedisHealth, checkSqlServerHealth, createStorageAdminApp, createStorageAdminServer };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { EnrichmentStageKey } from "@aiquants/enrichment-core";
|
|
2
|
+
export { SearchMode } from "@aiquants/enrichment-core";
|
|
3
|
+
import { EnrichmentStrategyRow, FailedSyncItem, QdrantStorageOverview, CircuitBreakerState, PipelineConfig, DocumentIngestPayload, FileInspectionResult, RecentIngestItem, OntologyStatusData } from "@aiquants/enrichment-react";
|
|
4
|
+
export { DocumentIngestLabel, DocumentIngestPayload, EnrichmentStrategyRow, FailedSyncItem, FileInspectionResult, FusionStrategy, MetadataSearchHit, MetadataSearchParams, MetadataSearchResult, OntologyStatusData, PipelineConfig, QdrantCollectionInfo, QdrantStorageOverview, RecentIngestItem, SearchHitGraphRelation, SearchHitScoreBreakdown, StrategyProvenance } from "@aiquants/enrichment-react";
|
|
5
|
+
import { ConfidentialityPolicyRow, TranscriptionTermRow, TranscriptionReferenceRow, PromptTemplateItem, ClassificationRuleItem, GraphSchemaStats, TriStoreAuditData, TriStoreReconcileResult, GraphTraversalRunner, GraphNodeIndexOutcome, SimulationRunner } from "@aiquants/governance-react";
|
|
6
|
+
export { ClassificationRuleItem as ClassificationRule, GraphNodeIndexOutcome, GraphNodeIndexPage, GraphNodeSummary, GraphSchemaStats, GraphTraversalInput, GraphTraversalOutcome, GraphTraversalRunner, PromptTemplateItem, SimulationOutcome, SimulationRunInput, SimulationRunResult, SimulationRunner, SimulationScoreSet, SimulationVerdictFlip, TriStoreAuditData, TriStoreReconcileResult } from "@aiquants/governance-react";
|
|
7
|
+
import * as react from "react";
|
|
8
|
+
import { ReactNode } from "react";
|
|
9
|
+
import { useFetcher } from "react-router";
|
|
10
|
+
interface DocumentIngestResult {
|
|
11
|
+
metadataId: number;
|
|
12
|
+
revision: number;
|
|
13
|
+
createdNew: boolean;
|
|
14
|
+
jobId: string;
|
|
15
|
+
}
|
|
16
|
+
interface ServiceHealthStatus {
|
|
17
|
+
serviceName: string;
|
|
18
|
+
category: "vector" | "graph" | "cache" | "database" | "api";
|
|
19
|
+
status: "connected" | "error";
|
|
20
|
+
version: string | null;
|
|
21
|
+
endpoint: string;
|
|
22
|
+
latencyMs: number;
|
|
23
|
+
details: Record<string, string | number | boolean | null>;
|
|
24
|
+
errorMessage?: string;
|
|
25
|
+
}
|
|
26
|
+
interface SystemInfrastructureHealth {
|
|
27
|
+
services: {
|
|
28
|
+
qdrant: ServiceHealthStatus;
|
|
29
|
+
neo4j: ServiceHealthStatus;
|
|
30
|
+
redis: ServiceHealthStatus;
|
|
31
|
+
sqlServer: ServiceHealthStatus;
|
|
32
|
+
quantsApi: ServiceHealthStatus;
|
|
33
|
+
};
|
|
34
|
+
allHealthy: boolean;
|
|
35
|
+
checkedAt: string;
|
|
36
|
+
}
|
|
37
|
+
interface SystemParameter {
|
|
38
|
+
key: string;
|
|
39
|
+
value: string;
|
|
40
|
+
category: string;
|
|
41
|
+
description: string;
|
|
42
|
+
data_type: "string" | "int" | "float" | "bool" | "json";
|
|
43
|
+
is_secret: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface PromptTemplateUpdate {
|
|
46
|
+
templateText: string;
|
|
47
|
+
modelName: string;
|
|
48
|
+
temperature: number;
|
|
49
|
+
maxOutputTokens: number;
|
|
50
|
+
responseSchema?: Record<string, unknown> | string | null;
|
|
51
|
+
endpointBaseUrl: string | null;
|
|
52
|
+
}
|
|
53
|
+
interface PolicyWithoutDestination {
|
|
54
|
+
confidentialityLevel: string;
|
|
55
|
+
capability: string;
|
|
56
|
+
promptKey: string;
|
|
57
|
+
modelProvider: string;
|
|
58
|
+
}
|
|
59
|
+
interface UnresolvedEntity {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
category: string;
|
|
63
|
+
occurrences: number;
|
|
64
|
+
co_occurrences: number;
|
|
65
|
+
suggested_action: "merge" | "promote";
|
|
66
|
+
}
|
|
67
|
+
type StageMetrics = Record<string, {
|
|
68
|
+
latency_p50_ms: number;
|
|
69
|
+
latency_p95_ms: number;
|
|
70
|
+
throughput_rps: number;
|
|
71
|
+
success_rate: number;
|
|
72
|
+
}>;
|
|
73
|
+
interface StorageAdminLoaderData {
|
|
74
|
+
tenantId: string;
|
|
75
|
+
featureFlags: Record<string, boolean>;
|
|
76
|
+
systemParameters: SystemParameter[];
|
|
77
|
+
promptTemplates: PromptTemplateItem[];
|
|
78
|
+
classificationRules: ClassificationRuleItem[];
|
|
79
|
+
classificationRuleConsumer: string | null;
|
|
80
|
+
syncCounts: Record<string, number>;
|
|
81
|
+
totalFiles: number;
|
|
82
|
+
failedSyncItems: FailedSyncItem[];
|
|
83
|
+
circuitBreakerStatus: Record<string, CircuitBreakerState>;
|
|
84
|
+
pipelineConfig: PipelineConfig;
|
|
85
|
+
stageMetrics: StageMetrics;
|
|
86
|
+
graphSchema: GraphSchemaStats;
|
|
87
|
+
enrichmentStrategies: EnrichmentStrategyRow[];
|
|
88
|
+
triStoreAuditData: TriStoreAuditData;
|
|
89
|
+
unresolvedEntities: UnresolvedEntity[];
|
|
90
|
+
qdrantCollections: QdrantStorageOverview;
|
|
91
|
+
systemHealth: SystemInfrastructureHealth;
|
|
92
|
+
recentIngestItems?: RecentIngestItem[];
|
|
93
|
+
ontologyStatus: OntologyStatusData;
|
|
94
|
+
confidentialityPolicies: ConfidentialityPolicyRow[];
|
|
95
|
+
transcriptionVocabulary: TranscriptionTermRow[];
|
|
96
|
+
transcriptionReferences: TranscriptionReferenceRow[];
|
|
97
|
+
unresolvedReferenceUris: string[];
|
|
98
|
+
policiesMissingDestination: PolicyWithoutDestination[];
|
|
99
|
+
}
|
|
100
|
+
interface EnrichmentStrategyUpdate {
|
|
101
|
+
strategyId: number;
|
|
102
|
+
domainId: number;
|
|
103
|
+
stage: EnrichmentStageKey;
|
|
104
|
+
enabled: boolean;
|
|
105
|
+
}
|
|
106
|
+
interface ConsoleConfigSnapshot {
|
|
107
|
+
readonly featureFlags: Record<string, boolean>;
|
|
108
|
+
readonly systemParameters: SystemParameter[];
|
|
109
|
+
readonly syncCounts: {
|
|
110
|
+
counts: Record<string, number>;
|
|
111
|
+
total: number;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
interface StorageAdminStore {
|
|
115
|
+
getFeatureFlags(tenantId: string): Promise<Record<string, boolean>>;
|
|
116
|
+
getEnrichmentStrategies(tenantId: string): Promise<EnrichmentStrategyRow[]>;
|
|
117
|
+
updateEnrichmentStrategy(tenantId: string, input: EnrichmentStrategyUpdate, actor: string): Promise<void>;
|
|
118
|
+
toggleFeatureFlag(tenantId: string, flagKey: string, enabled: boolean, actor: string): Promise<void>;
|
|
119
|
+
getSystemParameters(tenantId: string): Promise<SystemParameter[]>;
|
|
120
|
+
updateSystemParameter(tenantId: string, paramKey: string, paramValue: string, actor: string): Promise<void>;
|
|
121
|
+
getConfidentialityPolicies(tenantId: string): Promise<ConfidentialityPolicyRow[]>;
|
|
122
|
+
updateConfidentialityPolicy(tenantId: string, policy: ConfidentialityPolicyRow, actor: string): Promise<void>;
|
|
123
|
+
getTranscriptionVocabulary(tenantId: string): Promise<TranscriptionTermRow[]>;
|
|
124
|
+
saveTranscriptionTerm(tenantId: string, row: Omit<TranscriptionTermRow, "id"> & {
|
|
125
|
+
id: number | null;
|
|
126
|
+
}, actor: string): Promise<void>;
|
|
127
|
+
getTranscriptionReferences(tenantId: string): Promise<TranscriptionReferenceRow[]>;
|
|
128
|
+
saveTranscriptionReference(tenantId: string, row: Omit<TranscriptionReferenceRow, "id"> & {
|
|
129
|
+
id: number | null;
|
|
130
|
+
}, actor: string): Promise<void>;
|
|
131
|
+
getUnresolvedReferenceUris(tenantId: string): Promise<string[]>;
|
|
132
|
+
getPoliciesMissingDestination(tenantId: string): Promise<PolicyWithoutDestination[]>;
|
|
133
|
+
getPromptTemplates(tenantId: string): Promise<PromptTemplateItem[]>;
|
|
134
|
+
updatePromptTemplate(tenantId: string, templateKey: string, payload: PromptTemplateUpdate, actor: string): Promise<void>;
|
|
135
|
+
getClassificationRules(tenantId: string): Promise<ClassificationRuleItem[]>;
|
|
136
|
+
classificationRuleConsumer?: string;
|
|
137
|
+
reorderClassificationRules(tenantId: string, orderedRuleIds: number[], actor: string): Promise<void>;
|
|
138
|
+
getSyncCounts(tenantId: string): Promise<{
|
|
139
|
+
counts: Record<string, number>;
|
|
140
|
+
total: number;
|
|
141
|
+
}>;
|
|
142
|
+
getFailedSyncItems(tenantId: string): Promise<FailedSyncItem[]>;
|
|
143
|
+
retrySyncItem(tenantId: string, fileId: string, actor?: string, accessToken?: string): Promise<void>;
|
|
144
|
+
retryAllFailedSyncItems(tenantId: string, actor?: string, accessToken?: string): Promise<void>;
|
|
145
|
+
getGraphSchema(tenantId: string): Promise<GraphSchemaStats>;
|
|
146
|
+
getTriStoreAuditData(tenantId: string, snapshot: ConsoleConfigSnapshot): Promise<TriStoreAuditData>;
|
|
147
|
+
reconcileTriStore(tenantId: string, accessToken?: string): Promise<TriStoreReconcileResult>;
|
|
148
|
+
getUnresolvedEntities(tenantId: string): Promise<UnresolvedEntity[]>;
|
|
149
|
+
resolveEntity(tenantId: string, entityId: string, action: "merge" | "promote"): Promise<void>;
|
|
150
|
+
getQdrantCollections(tenantId: string): Promise<QdrantStorageOverview>;
|
|
151
|
+
getCircuitBreakerStatus(): Record<string, CircuitBreakerState>;
|
|
152
|
+
getPipelineConfig(tenantId: string, snapshot: ConsoleConfigSnapshot): Promise<PipelineConfig>;
|
|
153
|
+
getStageMetrics(): StageMetrics;
|
|
154
|
+
ingestDocument(tenantId: string, payload: DocumentIngestPayload, actor: string, accessToken?: string): Promise<DocumentIngestResult>;
|
|
155
|
+
inspectFileUri?(tenantId: string, fileUri: string, accessToken?: string): Promise<FileInspectionResult>;
|
|
156
|
+
getRecentIngestItems(tenantId: string): Promise<RecentIngestItem[]>;
|
|
157
|
+
getOntologyStatus(tenantId: string, snapshot: ConsoleConfigSnapshot): Promise<OntologyStatusData>;
|
|
158
|
+
}
|
|
159
|
+
type GraphReadOutcome = {
|
|
160
|
+
readonly ok: true;
|
|
161
|
+
readonly rows: readonly (readonly unknown[])[];
|
|
162
|
+
} | {
|
|
163
|
+
readonly ok: false;
|
|
164
|
+
readonly reason: string;
|
|
165
|
+
};
|
|
166
|
+
type GraphReader = (statement: string, parameters: Record<string, unknown>) => Promise<GraphReadOutcome>;
|
|
167
|
+
interface HealthProbeOptions {
|
|
168
|
+
qdrantUrl?: string;
|
|
169
|
+
qdrantApiKey?: string;
|
|
170
|
+
graphReader?: GraphReader | null;
|
|
171
|
+
neo4jBoltUri?: string;
|
|
172
|
+
redisClient?: {
|
|
173
|
+
ping: () => Promise<string>;
|
|
174
|
+
info: (section?: string) => Promise<string>;
|
|
175
|
+
dbSize?: () => Promise<number>;
|
|
176
|
+
} | null;
|
|
177
|
+
redisHost?: string;
|
|
178
|
+
redisPort?: number;
|
|
179
|
+
redisTls?: boolean;
|
|
180
|
+
sqlServerExecute?: () => Promise<{
|
|
181
|
+
version: string;
|
|
182
|
+
db_name: string;
|
|
183
|
+
}>;
|
|
184
|
+
sqlServerHost?: string;
|
|
185
|
+
sqlServerPort?: number;
|
|
186
|
+
sqlServerTls?: boolean;
|
|
187
|
+
backendApiHost?: string;
|
|
188
|
+
timeoutMs?: number;
|
|
189
|
+
tenantId?: string;
|
|
190
|
+
}
|
|
191
|
+
interface CreateStorageAdminAppOptions {
|
|
192
|
+
store: StorageAdminStore;
|
|
193
|
+
healthProbeOptions?: HealthProbeOptions;
|
|
194
|
+
resourceKey?: string;
|
|
195
|
+
basePath?: string;
|
|
196
|
+
requireUser?: (request: Request) => Promise<unknown>;
|
|
197
|
+
requirePermission?: (request: Request, query: {
|
|
198
|
+
resourceKey: string;
|
|
199
|
+
action: "read" | "update";
|
|
200
|
+
}) => Promise<unknown>;
|
|
201
|
+
resolveTenantId?: (request: Request) => Promise<string> | string;
|
|
202
|
+
authorizeIngest: (request: Request, payload: DocumentIngestPayload) => Promise<string | null>;
|
|
203
|
+
}
|
|
204
|
+
interface StorageAdminFetcher {
|
|
205
|
+
state: "idle" | "submitting" | "loading";
|
|
206
|
+
formData?: FormData | null;
|
|
207
|
+
data?: {
|
|
208
|
+
error?: string;
|
|
209
|
+
inspection?: FileInspectionResult;
|
|
210
|
+
result?: unknown;
|
|
211
|
+
} | null;
|
|
212
|
+
submit: ReturnType<typeof useFetcher>["submit"];
|
|
213
|
+
}
|
|
214
|
+
interface StorageAdminConsoleViewProps {
|
|
215
|
+
data?: StorageAdminLoaderData;
|
|
216
|
+
fetcher?: StorageAdminFetcher;
|
|
217
|
+
renderHeader?: (props: {
|
|
218
|
+
title: string;
|
|
219
|
+
tenantId: string;
|
|
220
|
+
}) => ReactNode;
|
|
221
|
+
onTraverseGraph?: GraphTraversalRunner;
|
|
222
|
+
onBrowseGraphNodes?: (label: string, pageIndex: number) => Promise<GraphNodeIndexOutcome>;
|
|
223
|
+
onSimulateGovernance?: SimulationRunner;
|
|
224
|
+
onRefreshIngestQueue?: IngestQueueRefresher;
|
|
225
|
+
}
|
|
226
|
+
type IngestQueueRefresher = () => Promise<readonly RecentIngestItem[]>;
|
|
227
|
+
declare function StorageAdminConsoleView(props?: StorageAdminConsoleViewProps): react.JSX.Element;
|
|
228
|
+
declare function createStorageAdminApp(options: CreateStorageAdminAppOptions): {
|
|
229
|
+
loader: (args: {
|
|
230
|
+
request: Request;
|
|
231
|
+
}) => Promise<StorageAdminLoaderData>;
|
|
232
|
+
action: (args: {
|
|
233
|
+
request: Request;
|
|
234
|
+
}) => Promise<Response>;
|
|
235
|
+
View: typeof StorageAdminConsoleView;
|
|
236
|
+
server: {
|
|
237
|
+
loader: (args: {
|
|
238
|
+
request: Request;
|
|
239
|
+
}) => Promise<StorageAdminLoaderData>;
|
|
240
|
+
action: (args: {
|
|
241
|
+
request: Request;
|
|
242
|
+
}) => Promise<Response>;
|
|
243
|
+
};
|
|
244
|
+
};
|
|
245
|
+
declare function checkQdrantHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
246
|
+
declare function checkNeo4jHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
247
|
+
declare function checkRedisHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
248
|
+
declare function checkSqlServerHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
249
|
+
declare function checkBackendApiHealth(opts?: HealthProbeOptions): Promise<ServiceHealthStatus>;
|
|
250
|
+
declare function checkAllSystemHealth(opts?: HealthProbeOptions): Promise<SystemInfrastructureHealth>;
|
|
251
|
+
declare function createStorageAdminServer(options: CreateStorageAdminAppOptions): {
|
|
252
|
+
loader: (args: {
|
|
253
|
+
request: Request;
|
|
254
|
+
}) => Promise<StorageAdminLoaderData>;
|
|
255
|
+
action: (args: {
|
|
256
|
+
request: Request;
|
|
257
|
+
}) => Promise<Response>;
|
|
258
|
+
};
|
|
259
|
+
export { type ConsoleConfigSnapshot, type CreateStorageAdminAppOptions, type DocumentIngestResult, type EnrichmentStrategyUpdate, type GraphReadOutcome, type GraphReader, type HealthProbeOptions, type IngestQueueRefresher, type PolicyWithoutDestination, type PromptTemplateUpdate, type ServiceHealthStatus, type StageMetrics, StorageAdminConsoleView, type StorageAdminConsoleViewProps, type StorageAdminFetcher, type StorageAdminLoaderData, type StorageAdminStore, type SystemInfrastructureHealth, type SystemParameter, type UnresolvedEntity, checkAllSystemHealth, checkBackendApiHealth, checkNeo4jHealth, checkQdrantHealth, checkRedisHealth, checkSqlServerHealth, createStorageAdminApp, createStorageAdminServer };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{EnrichmentSyncStatusSchema as ie,GRAPH_INDEX_LIMITS as ae}from"@aiquants/enrichment-core";import{DocumentIngestConsole as oe,EnrichmentStrategyBoard as le,InfrastructureHealthMonitor as ce,MetadataSearchWorkbench as ue,OntologyStatusCard as de,QdrantStorageCard as pe,RAGPipelineGraphViewer as me,SyncStatusMonitor as ge}from"@aiquants/enrichment-react";import{ClassificationRuleEditor as fe,ConfidentialityPolicyBoard as ye,FeatureFlagBoard as Se,GovernanceDryRunConsole as be,KnowledgeGraphExplorer as he,PromptTemplateConsole as ve,SystemParameterTable as Re,TranscriptionAdaptationBoard as Ie,TriStoreIntegrityAudit as we}from"@aiquants/governance-react";import{useCallback as Te,useEffect as Pe,useRef as K,useState as L}from"react";import{useFetcher as _e,useLoaderData as Ae,useSearchParams as Ee}from"react-router";import{jsx as p,jsxs as v}from"react/jsx-runtime";var Q="tab",x=[{key:"search",label:"\u30E1\u30BF\u30C7\u30FC\u30BF\u691C\u7D22\u30EF\u30FC\u30AF\u30D9\u30F3\u30C1"},{key:"ingest",label:"\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u53D6\u308A\u8FBC\u307F & \u30E1\u30BF\u751F\u6210"},{key:"rag-pipeline",label:"RAG \u5B9F\u884C\u57FA\u76E4 & \u63A5\u7D9A\u72B6\u614B"},{key:"knowledge-graph",label:"\u30CA\u30EC\u30C3\u30B8\u30B0\u30E9\u30D5\u63A2\u7D22"},{key:"parameters",label:"\u30E2\u30C7\u30EB & \u30D1\u30E9\u30E1\u30FC\u30BF\u8A2D\u5B9A"},{key:"prompts",label:"\u30D7\u30ED\u30F3\u30D7\u30C8 & \u30C9\u30E9\u30A4\u30E9\u30F3"},{key:"data-retention",label:"\u30C7\u30FC\u30BF\u4FDD\u6301 & \u6574\u5408\u6027\u76E3\u67FB"}];function Ne(t){return t!==null&&x.some(e=>e.key===t)}var xe={state:"idle",formData:null,data:null,submit:()=>Promise.resolve()};function V({data:t,fetcher:e,renderHeader:a,onTraverseGraph:i,onBrowseGraphNodes:o,onSimulateGovernance:n,onRefreshIngestQueue:s}){let[l,d]=L(null),[m,f]=L(null),[y,b]=L(!1),u=Te((r,S)=>{o!==void 0&&(b(!0),o(r,S).then(h=>{b(!1),f(h.ok?null:h.reason),h.ok&&d(h.page)}))},[o]),[N,_]=Ee(),w=N.get(Q),g=Ne(w)?w:x[0].key,A=r=>{_(S=>{let h=new URLSearchParams(S);return h.set(Q,r),h},{replace:!1,preventScrollReset:!0})},E=ke(t.recentIngestItems,s,g==="ingest"),c=E===t.recentIngestItems?t:{...t,recentIngestItems:E===void 0?void 0:[...E]},I=K({}),R=(r,S)=>{let h=x.length-1,T;if(r.key==="ArrowRight"||r.key==="ArrowDown")T=S===h?0:S+1;else if(r.key==="ArrowLeft"||r.key==="ArrowUp")T=S===0?h:S-1;else if(r.key==="Home")T=0;else if(r.key==="End")T=h;else return;r.preventDefault();let j=x[T].key;A(j),I.current[j]?.focus()},C={...c.featureFlags};if(e.formData&&e.formData.get("intent")==="toggle_flag"){let r=String(e.formData.get("flagKey")??""),S=String(e.formData.get("enabled")??"")==="true";r&&(C[r]=S)}let k=e.data?.error,U=e.data&&"inspection"in e.data?e.data.inspection:void 0,F=e.state!=="idle"&&e.formData?.get("intent")==="inspect_uri",H=e.state!=="idle"&&e.formData?.get("intent")==="ingest_document";return v("div",{className:"container mx-auto space-y-6 p-6 font-sans text-slate-900","data-testid":"storage-admin-console",children:[k&&p("div",{className:"rounded-lg border border-red-200 bg-red-50 p-4 font-medium text-red-700 text-sm shadow-sm",role:"alert","data-testid":"storage-admin-error-alert",children:k}),a?a({title:"\u30B9\u30C8\u30EC\u30FC\u30B8 AI \u30A8\u30F3\u30EA\u30C3\u30C1\u30E1\u30F3\u30C8 & \u30AC\u30D0\u30CA\u30F3\u30B9\u904B\u7528\u7BA1\u7406",tenantId:c.tenantId}):v("header",{className:"flex flex-col justify-between gap-2 border-slate-200 border-b pb-4 md:flex-row md:items-center",children:[v("div",{children:[p("h1",{className:"font-bold text-2xl tracking-tight",children:"\u30B9\u30C8\u30EC\u30FC\u30B8 AI \u30A8\u30F3\u30EA\u30C3\u30C1\u30E1\u30F3\u30C8 & \u30AC\u30D0\u30CA\u30F3\u30B9\u904B\u7528\u7BA1\u7406"}),v("p",{className:"mt-1 text-slate-500 text-sm",children:["\u30C6\u30CA\u30F3\u30C8: ",p("code",{className:"font-semibold text-slate-800",children:c.tenantId})," | \u5168\u30B7\u30B9\u30C6\u30E0\u72B6\u614B\u30FB\u30D1\u30E9\u30E1\u30FC\u30BF\u5236\u5FA1\u30FB\u6574\u5408\u6027\u76E3\u67FB"]})]}),p("div",{className:"flex items-center gap-2",children:v("button",{type:"button","data-testid":"header-health-status-button",onClick:()=>A("rag-pipeline"),className:"inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-1.5 font-medium text-slate-700 text-xs transition-colors hover:bg-slate-100",children:[p("span",{className:`h-2 w-2 rounded-full ${c.systemHealth.allHealthy?"bg-emerald-500":"bg-amber-500"}`}),v("span",{children:["\u5468\u8FBA\u6A5F\u80FD: ",c.systemHealth.allHealthy?"\u5168\u30B5\u30FC\u30D3\u30B9\u6B63\u5E38":"\u63A5\u7D9A\u8981\u78BA\u8A8D"]})]})})]}),v("div",{className:"w-full space-y-6",children:[p("div",{className:"grid w-full grid-cols-2 gap-1 rounded-xl bg-slate-100 p-1 md:grid-cols-8",role:"tablist","aria-label":"Storage Administration Console Tabs",children:x.map((r,S)=>{let h=g===r.key;return p("button",{id:`tab-${r.key}`,type:"button",role:"tab",ref:T=>{I.current[r.key]=T},"aria-selected":h,"aria-controls":`panel-${r.key}`,tabIndex:h?0:-1,"data-testid":`tab-trigger-${r.key}`,onKeyDown:T=>R(T,S),onClick:()=>A(r.key),className:`rounded-lg px-3 py-2.5 text-center font-medium text-sm transition-all ${h?"bg-white text-slate-900 shadow-sm":"text-slate-600 hover:bg-slate-200/50 hover:text-slate-900"}`,children:r.label},r.key)})}),g==="search"&&p("div",{role:"tabpanel",id:"panel-search","aria-labelledby":"tab-search",className:"space-y-6","data-testid":"tab-content-search",children:p(ue,{tenantId:c.tenantId,circuitBreakerStatus:c.circuitBreakerStatus})}),g==="ingest"&&p("div",{role:"tabpanel",id:"panel-ingest","aria-labelledby":"tab-ingest",className:"space-y-6","data-testid":"tab-content-ingest",children:p(oe,{tenantId:c.tenantId,policies:c.confidentialityPolicies,recentItems:c.recentIngestItems,inspectionResult:U,isInspecting:F,isSubmitting:H,onInspectUri:r=>{e.submit({intent:"inspect_uri",fileUri:r},{method:"post"})},onIngestDocument:r=>{e.submit({intent:"ingest_document",payload:JSON.stringify(r)},{method:"post"})},onRetryItem:r=>{e.submit({intent:"retry_job",fileId:String(r)},{method:"post"})}})}),g==="rag-pipeline"&&v("div",{role:"tabpanel",id:"panel-rag-pipeline","aria-labelledby":"tab-rag-pipeline",className:"space-y-6","data-testid":"tab-content-rag-pipeline",children:[p(me,{pipelineConfig:c.pipelineConfig,circuitBreakerStatus:c.circuitBreakerStatus,stageMetrics:c.stageMetrics}),p(le,{strategies:c.enrichmentStrategies,featureFlags:c.featureFlags,isUpdating:e.state!=="idle",onToggleStage:(r,S,h)=>e.submit({intent:"update_enrichment_strategy",strategyId:String(r.id),domainId:String(r.domainId),stage:S,enabled:String(h)},{method:"post"})}),p(ce,{health:c.systemHealth,isRefreshing:e.state!=="idle",onRefresh:()=>e.submit({intent:"refresh_health"},{method:"post"})})]}),g==="knowledge-graph"&&v("div",{role:"tabpanel",id:"panel-knowledge-graph","aria-labelledby":"tab-knowledge-graph",className:"space-y-6","data-testid":"tab-content-knowledge-graph",children:[p(de,{tenantId:c.tenantId,ontologyStatus:c.ontologyStatus}),p(he,{topologyMaxLabels:ae.topologyLabels.default,schema:c.graphSchema,tenantId:c.tenantId,unresolvedEntities:c.unresolvedEntities,onTraverse:i,onBrowseLabel:o===void 0?void 0:u,nodeIndexPage:l,nodeIndexFailure:m,isNodeIndexLoading:y,onResolveEntity:(r,S)=>{e.submit({intent:"resolve_entity",entityId:r,action:S},{method:"post"})}})]}),g==="parameters"&&v("div",{role:"tabpanel",id:"panel-parameters","aria-labelledby":"tab-parameters",className:"space-y-6","data-testid":"tab-content-parameters",children:[v("div",{className:"grid grid-cols-1 gap-6 md:grid-cols-2",children:[p(Se,{flags:C,isUpdating:e.state!=="idle",onToggleFlag:(r,S)=>{e.submit({intent:"toggle_flag",flagKey:r,enabled:String(S)},{method:"post"})}}),p(fe,{rules:c.classificationRules,consultedBy:c.classificationRuleConsumer,onReorderRules:r=>{e.submit({intent:"reorder_rules",orderedRuleIds:JSON.stringify(r)},{method:"post"})}})]}),c.policiesMissingDestination.length>0&&v("div",{"data-testid":"policies-missing-destination",role:"alert",style:{padding:"10px 12px",borderRadius:"6px",backgroundColor:"#fef2f2",color:"#b91c1c",fontSize:"12px"},children:[p("strong",{children:"\u6B21\u306E\u533A\u5206\u30FB\u6A5F\u80FD\u306F\u5B9F\u884C\u6642\u306B\u5931\u6557\u3057\u307E\u3059\u3002"})," \u53C2\u7167\u3059\u308B\u30D7\u30ED\u30F3\u30D7\u30C8\u884C\u306B\u5B9B\u5148\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",p("ul",{style:{margin:"6px 0 0",paddingInlineStart:"18px"},children:c.policiesMissingDestination.map(r=>v("li",{"data-testid":`missing-destination-${r.confidentialityLevel}-${r.capability}`,children:[r.confidentialityLevel," / ",r.capability," \u2192 ",r.promptKey," (",r.modelProvider,") \u306E ",p("code",{children:"extra_params.base_url"})]},`${r.confidentialityLevel}:${r.capability}`))}),p("span",{style:{display:"block",marginTop:"4px",fontSize:"11px"},children:"\u5B9B\u5148\u3092\u8A2D\u5B9A\u3057\u3066\u3082\u3001\u305D\u306E\u30DB\u30B9\u30C8\u304C\u914D\u5099\u5185\u3068\u3057\u3066\u767B\u9332\u3055\u308C\u3066\u3044\u306A\u3051\u308C\u3070\u62D2\u5426\u3055\u308C\u307E\u3059\u3002"})]}),p(ye,{policies:c.confidentialityPolicies,promptKeys:c.promptTemplates.map(r=>r.template_key),isUpdating:e.state!=="idle",onChangePolicy:r=>{e.submit({intent:"update_confidentiality_policy",confidentialityLevel:r.confidentialityLevel,capability:r.capability,isEnabled:String(r.isEnabled),allowCloudProvider:String(r.allowCloudProvider),promptKey:r.promptKey??""},{method:"post"})}}),p(Ie,{vocabulary:c.transcriptionVocabulary,references:c.transcriptionReferences,unresolvedUris:c.unresolvedReferenceUris,isUpdating:e.state!=="idle",onSaveTerm:r=>{e.submit({intent:"save_transcription_term",id:r.id===null?"":String(r.id),term:r.term,reading:r.reading??"",boost:r.boost===null?"":String(r.boost),domainKey:r.domainKey??"",isActive:String(r.isActive)},{method:"post"})},onSaveReference:r=>{e.submit({intent:"save_transcription_reference",id:r.id===null?"":String(r.id),fileUri:r.fileUri,domainKey:r.domainKey??"",isActive:String(r.isActive)},{method:"post"})}}),p(Re,{parameters:c.systemParameters,onSaveParameter:(r,S)=>{e.submit({intent:"update_parameter",paramKey:r,paramValue:String(S)},{method:"post"})}})]}),g==="prompts"&&v("div",{role:"tabpanel",id:"panel-prompts","aria-labelledby":"tab-prompts",className:"space-y-6","data-testid":"tab-content-prompts",children:[p(ve,{templates:c.promptTemplates,isSaving:e.state!=="idle",onSaveTemplate:r=>{e.submit({intent:"update_prompt",templateKey:r.template_key,payload:JSON.stringify({templateText:r.template_text,modelName:r.model_name,temperature:r.temperature,maxOutputTokens:r.max_output_tokens,responseSchema:r.response_schema,endpointBaseUrl:r.endpoint_base_url??null})},{method:"post"})}}),p(be,{onSimulate:n})]}),g==="data-retention"&&v("div",{role:"tabpanel",id:"panel-data-retention","aria-labelledby":"tab-data-retention",className:"space-y-6","data-testid":"tab-content-data-retention",children:[p(we,{auditData:c.triStoreAuditData,onTriggerReconcile:()=>{e.submit({intent:"reconcile"},{method:"post"})}}),v("div",{className:"grid grid-cols-1 gap-6 md:grid-cols-2",children:[p(ge,{counts:c.syncCounts,totalFiles:c.totalFiles,failedItems:c.failedSyncItems,onRetryItem:r=>{e.submit({intent:"retry_job",fileId:String(r)},{method:"post"})},onRetryAll:()=>{e.submit({intent:"retry_all_failed"},{method:"post"})}}),p(pe,{collections:c.qdrantCollections.collections,probeFailure:c.qdrantCollections.probe_failure,health:{healthy:c.systemHealth.services.qdrant.status==="connected",latency_ms:c.systemHealth.services.qdrant.latencyMs}})]})]})]})]})}var Ce=new Set(ie.options.filter(t=>t!=="SYNCED"&&!t.startsWith("FAILED"))),$=2e3;function ke(t,e,a){let[i,o]=L(null),n=K(e);n.current=e;let s=K(t);s.current!==t&&(s.current=t,i!==null&&o(null));let l=i??t,d=l?.some(m=>Ce.has(m.syncStatus))===!0;return Pe(()=>{if(!(a&&d&&n.current))return;let m=!1,f,y=async()=>{let b=n.current;if(!(m||!b)){try{let u=await b();if(m)return;o(u)}catch{if(m)return}f=setTimeout(y,$)}};return f=setTimeout(y,$),()=>{m=!0,f!==void 0&&clearTimeout(f)}},[d,a]),l}function je(t){let e=Ae(),a=_e(),i=t.data??e,o=t.fetcher??a;return i?p(V,{data:i,fetcher:o,onRefreshIngestQueue:t.onRefreshIngestQueue,renderHeader:t.renderHeader,onTraverseGraph:t.onTraverseGraph,onBrowseGraphNodes:t.onBrowseGraphNodes,onSimulateGovernance:t.onSimulateGovernance}):p("div",{className:"p-8 text-center text-slate-500","data-testid":"storage-admin-loading",children:"\u30C7\u30FC\u30BF\u8AAD\u307F\u8FBC\u307F\u4E2D..."})}function J(t={}){return t.data?p(V,{data:t.data,fetcher:t.fetcher??xe,renderHeader:t.renderHeader,onTraverseGraph:t.onTraverseGraph,onBrowseGraphNodes:t.onBrowseGraphNodes,onSimulateGovernance:t.onSimulateGovernance}):p(je,{...t})}import{AuthzDeniedError as Z}from"@aiquants/authz-core";import{isEnrichmentStageKey as Me}from"@aiquants/enrichment-core";import{CLOUD_CAPABLE_CAPABILITIES as Ke,ConfidentialityLevelSchema as B,GovernedCapabilitySchema as qe}from"@aiquants/governance-core";function P(t){if(typeof globalThis<"u"&&"process"in globalThis)return globalThis.process?.env?.[t]}function O(t,e){let a=t?.trim();if(!a)throw new Error(`${e} is not configured; this probe will not guess an endpoint to send credentials to.`);return a}function z(t,e,a){let i=t??(e?.trim()?Number(e):Number.NaN);if(!Number.isInteger(i)||i<=0||i>65535)throw new Error(`${a} is not configured with a valid port; this probe will not guess one.`);return i}function Y(t,e){if(t!==void 0)return t;let a=e?.trim().toLowerCase();if(!(a===void 0||a===""))return a==="1"||a==="true"||a==="yes"||a==="on"}function W(t){let e=t.trim().split("://",1)[0]?.toLowerCase();if(e&&t.includes("://"))return e.endsWith("s")||e.includes("+s")}function Le(t){let a=(t.split("://").pop()??"").split("/",1)[0]??"",i=a.split(":").pop();if(!i||i===a)return;let o=Number(i);return Number.isInteger(o)&&o>0&&o<=65535?o:void 0}async function q(t,e){let a;try{return await Promise.race([t,new Promise((i,o)=>{a=setTimeout(()=>o(new Error(`Probe timed out after ${e}ms`)),e)})])}finally{a!==void 0&&clearTimeout(a)}}async function Oe(t){let e=t?.qdrantApiKey??P("QDRANT_API_KEY")??"",a=t?.timeoutMs??3e3,i=Date.now(),o="";try{o=O(t?.qdrantUrl??P("QDRANT_URL"),"QDRANT_URL");let n={};e&&(n["api-key"]=e);let[s,l]=await Promise.all([fetch(`${o}/`,{headers:n,signal:AbortSignal.timeout(a)}),fetch(`${o}/collections`,{headers:n,signal:AbortSignal.timeout(a)})]);if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);if(!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText} (/collections)`);let d=await s.json(),m=Date.now()-i,y=(await l.json()).result?.collections?.length??0;return{serviceName:"Qdrant",category:"vector",status:"connected",version:d.version??"unknown",endpoint:o,latencyMs:m,details:{engine:d.title??"qdrant",collectionsCount:y,restPort:Le(o)??null,tls:W(o)??null}}}catch(n){let s=Date.now()-i,l=n instanceof Error?n.message:String(n);return{serviceName:"Qdrant",category:"vector",status:"error",version:null,endpoint:o,latencyMs:s,details:{},errorMessage:l}}}async function De(t){let e=t?.timeoutMs??3e3,a=Date.now(),i=t?.neo4jBoltUri??P("NEO4J_URI")??"";try{let o=t?.graphReader;if(!o)throw new Error("Graph reader not configured");let n=t?.tenantId,[s,l]=await Promise.all([q(o("CALL dbms.components() YIELD versions, edition RETURN versions[0] AS version, edition",{}),e),q(n?o("MATCH (n {tenantId: $tenantId}) RETURN count(n) AS node_count",{tenantId:n}):o("RETURN null AS node_count",{}),e)]);if(!s.ok)throw new Error(s.reason);if(!l.ok)throw new Error(l.reason);let[d,m]=s.rows[0]??[],f=l.rows[0]?.[0],y=Date.now()-a;return{serviceName:"Neo4j",category:"graph",status:"connected",version:typeof d=="string"?d:"unknown",endpoint:i,latencyMs:y,details:{edition:typeof m=="string"?m:"unknown",boltUri:i,nodeCount:typeof f=="number"?f:null,tls:W(i)??null}}}catch(o){let n=Date.now()-a,s=o instanceof Error?o.message:String(o);return{serviceName:"Neo4j",category:"graph",status:"error",version:null,endpoint:i,latencyMs:n,details:{},errorMessage:s}}}async function Ue(t){let e=Date.now(),a="",i=Y(t?.redisTls,P("REDIS_TLS")),o=Number.NaN;try{let n=t?.redisClient;if(!n)throw new Error("Redis client not configured");let s=O(t?.redisHost??P("REDIS_HOST"),"REDIS_HOST");o=z(t?.redisPort,P("REDIS_PORT"),"REDIS_PORT"),a=`${i===!1?"redis":"rediss"}://${s}:${o}`,await n.ping();let d=(await n.info("server")).match(/redis_version:([^\r\n]+)/),m=d?d[1]:"unknown",f=null;if(typeof n.dbSize=="function")try{f=await n.dbSize()}catch{f=null}let y=Date.now()-e;return{serviceName:"Redis",category:"cache",status:"connected",version:m,endpoint:a,latencyMs:y,details:{totalKeys:f,port:o,tls:i??null,database:0}}}catch(n){let s=Date.now()-e,l=n instanceof Error?n.message:String(n);return{serviceName:"Redis",category:"cache",status:"error",version:null,endpoint:a,latencyMs:s,details:{},errorMessage:l}}}async function Fe(t){let e=Date.now(),a="",i=Y(t?.sqlServerTls,P("SQL_SERVER_TLS")),o=Number.NaN;try{let n=t?.sqlServerExecute;if(!n)throw new Error("SQL Server executor not configured");let s=O(t?.sqlServerHost??P("SQL_SERVER_HOST"),"SQL_SERVER_HOST");o=z(t?.sqlServerPort,P("SQL_SERVER_PORT"),"SQL_SERVER_PORT"),a=`${s}:${o}`;let l=await n(),d=l.version??"unknown",m=typeof l.db_name=="string"&&l.db_name!==""?l.db_name:null,f=d.split(`
|
|
2
|
+
`)[0]??d,y=f.match(/Microsoft SQL Server \d+ \([^)]+\)/),b=y?y[0].replace("Microsoft SQL Server ",""):f.substring(0,30),u=Date.now()-e;return{serviceName:"SQL Server",category:"database",status:"connected",version:b,endpoint:a,latencyMs:u,details:{database:m,port:o,tls:i??null,fullVersion:f}}}catch(n){let s=Date.now()-e,l=n instanceof Error?n.message:String(n);return{serviceName:"SQL Server",category:"database",status:"error",version:null,endpoint:a,latencyMs:s,details:{},errorMessage:l}}}async function He(t){let e=t?.timeoutMs??3e3,a=Date.now(),i="";try{i=O(t?.backendApiHost??P("BACKEND_API_HOST"),"BACKEND_API_HOST");let o=await fetch(`${i}/openapi.json`,{signal:AbortSignal.timeout(e)});if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);let n=await o.json(),s=Object.keys(n.paths??{}).length,l=Date.now()-a;return{serviceName:"AI Quant API",category:"api",status:"connected",version:typeof n.info?.version=="string"&&n.info.version!==""?n.info.version:null,endpoint:i,latencyMs:l,details:{title:n.info?.title??"AI Quant API",endpointsCount:s}}}catch(o){let n=Date.now()-a,s=o instanceof Error?o.message:String(o);return{serviceName:"AI Quant API",category:"api",status:"error",version:null,endpoint:i,latencyMs:n,details:{},errorMessage:s}}}async function X(t){let[e,a,i,o,n]=await Promise.all([Oe(t),De(t),Ue(t),Fe(t),He(t)]),s=e.status==="connected"&&a.status==="connected"&&i.status==="connected"&&o.status==="connected"&&n.status==="connected";return{services:{qdrant:e,neo4j:a,redis:i,sqlServer:o,quantsApi:n},allHealthy:s,checkedAt:new Date().toISOString()}}function ee(t){let{store:e,healthProbeOptions:a,resourceKey:i="storage_admin",requireUser:o,requirePermission:n,resolveTenantId:s,authorizeIngest:l}=t;async function d(y){return s?await s(y):"default"}async function m(y){let{request:b}=y;if(o&&!await o(b))throw new Response("\u8A8D\u8A3C\u304C\u5FC5\u8981\u3067\u3059\u3002",{status:401});if(n)try{await n(b,{resourceKey:i,action:"read"})}catch(M){throw M instanceof Z?new Response("\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093\u3002",{status:403}):M}let u=await d(b),[N,_,w]=await Promise.all([e.getFeatureFlags(u),e.getSystemParameters(u),e.getSyncCounts(u)]),g={featureFlags:N,systemParameters:_,syncCounts:w},[A,E,c,I,R,C,k,U,F,H,r,S,h,T,j,te,ne]=await Promise.all([e.getConfidentialityPolicies(u),e.getTranscriptionVocabulary(u),e.getTranscriptionReferences(u),e.getUnresolvedReferenceUris(u),e.getPoliciesMissingDestination(u),e.getPromptTemplates(u),e.getClassificationRules(u),e.getFailedSyncItems(u),e.getGraphSchema(u),e.getTriStoreAuditData(u,g),e.getUnresolvedEntities(u),e.getQdrantCollections(u),X({...a,tenantId:u}),e.getPipelineConfig(u,g),e.getRecentIngestItems(u),e.getOntologyStatus(u,g),e.getEnrichmentStrategies(u)]),re=e.getCircuitBreakerStatus(),se=e.getStageMetrics();return{tenantId:u,featureFlags:g.featureFlags,confidentialityPolicies:A,transcriptionVocabulary:E,transcriptionReferences:c,unresolvedReferenceUris:I,policiesMissingDestination:R,systemParameters:g.systemParameters,promptTemplates:C,classificationRules:k,classificationRuleConsumer:e.classificationRuleConsumer??null,syncCounts:g.syncCounts.counts,totalFiles:g.syncCounts.total,failedSyncItems:U,circuitBreakerStatus:re,pipelineConfig:T,stageMetrics:se,graphSchema:F,enrichmentStrategies:ne,triStoreAuditData:H,unresolvedEntities:r,qdrantCollections:S,systemHealth:h,recentIngestItems:j,ontologyStatus:te}}async function f(y){let{request:b}=y,u=null,N;if(o){let I=await o(b);if(!I)return Response.json({error:"\u8A8D\u8A3C\u304C\u5FC5\u8981\u3067\u3059\u3002"},{status:401});let R=I;u=R.email||R.id||R.name||null,typeof R.accessToken=="string"&&R.accessToken!=="mock-access-token"&&(N=R.accessToken)}if(!u)return Response.json({error:"\u64CD\u4F5C\u8005\u3092\u7279\u5B9A\u3067\u304D\u306A\u3044\u305F\u3081\u8A2D\u5B9A\u3092\u5909\u66F4\u3067\u304D\u307E\u305B\u3093\u3002"},{status:403});if(n)try{await n(b,{resourceKey:i,action:"update"})}catch(I){if(I instanceof Z)return Response.json({error:"\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093\u3002"},{status:403});throw I}let _=await d(b),w=await b.formData(),g=String(w.get("intent")??"");if(g==="refresh_health")return Response.json({success:!0,refreshed:!0});let A=await Be(e,_,g,w,u);if(A)return A;let E=await Qe(e,_,g,w,u,N);if(E)return E;if(g==="resolve_entity"){let I=String(w.get("entityId")??""),R=String(w.get("action")??"");return!I||R!=="merge"&&R!=="promote"?Response.json({error:"Valid entityId and action ('merge' | 'promote') are required"},{status:400}):(await e.resolveEntity(_,I,R),Response.json({success:!0,entityId:I,action:R}))}let c=await Ve(e,_,g,w,u,b,l,N);return c||Response.json({error:`Unknown intent: ${g}`},{status:400})}return{loader:m,action:f}}function G(t){let e=String(t??"").trim();return e===""?null:e}function D(t){let e=String(t??"").trim();if(e==="")return null;let a=Number(e);if(!(!Number.isSafeInteger(a)||a<=0))return a}function Ge(t){let e=String(t??"").trim();if(e==="")return null;let a=Number(e);if(!(!Number.isFinite(a)||a<=0))return a}async function Be(t,e,a,i,o){if(a==="update_enrichment_strategy"){let n=String(i.get("stage")??"");if(!Me(n))return Response.json({error:"stage must be a canonical enrichment stage key"},{status:400});let s=D(i.get("strategyId")),l=D(i.get("domainId"));if(s==null||l===void 0||l===null)return Response.json({error:"strategyId and domainId must be positive integers naming existing rows"},{status:400});let d=String(i.get("enabled")??"")==="true";try{await t.updateEnrichmentStrategy(e,{strategyId:s,domainId:l,stage:n,enabled:d},o)}catch(m){return Response.json({error:m instanceof Error?m.message:"\u53D6\u308A\u8FBC\u307F\u6226\u7565\u3092\u66F4\u65B0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002"},{status:400})}return Response.json({success:!0,strategyId:s,domainId:l,stage:n,enabled:d})}if(a==="toggle_flag"){let n=String(i.get("flagKey")??""),s=String(i.get("enabled")??"")==="true";return n?(await t.toggleFeatureFlag(e,n,s,o),Response.json({success:!0,flagKey:n,enabled:s})):Response.json({error:"flagKey is required"},{status:400})}if(a==="update_confidentiality_policy"){let n=String(i.get("confidentialityLevel")??""),s=String(i.get("capability")??"");if(!(B.safeParse(n).success&&qe.safeParse(s).success))return Response.json({error:"confidentialityLevel and capability must be canonical values"},{status:400});let l=String(i.get("allowCloudProvider")??"")==="true";if(l&&!Ke.includes(s))return Response.json({error:`${s} sends nothing outside the deployment, so it has no cloud permission to grant`},{status:400});let d=String(i.get("promptKey")??"");return await t.updateConfidentialityPolicy(e,{confidentialityLevel:n,capability:s,isEnabled:String(i.get("isEnabled")??"")==="true",allowCloudProvider:l,promptKey:d===""?null:d},o),Response.json({success:!0,confidentialityLevel:n,capability:s})}if(a==="save_transcription_term"){let n=String(i.get("term")??"").trim();if(!n)return Response.json({error:"term is required"},{status:400});let s=Ge(i.get("boost"));if(s===void 0)return Response.json({error:"boost must be a number greater than zero, or absent to let the service decide"},{status:400});let l=D(i.get("id"));return l===void 0?Response.json({error:"id must be a positive integer naming an existing row, or absent for a new one"},{status:400}):(await t.saveTranscriptionTerm(e,{id:l,term:n,reading:G(i.get("reading")),boost:s,domainKey:G(i.get("domainKey")),isActive:String(i.get("isActive")??"true")==="true"},o),Response.json({success:!0,term:n}))}if(a==="save_transcription_reference"){let n=String(i.get("fileUri")??"").trim();if(!n)return Response.json({error:"fileUri is required"},{status:400});let s=D(i.get("id"));return s===void 0?Response.json({error:"id must be a positive integer naming an existing row, or absent for a new one"},{status:400}):(await t.saveTranscriptionReference(e,{id:s,fileUri:n,domainKey:G(i.get("domainKey")),isActive:String(i.get("isActive")??"true")==="true"},o),Response.json({success:!0,fileUri:n}))}if(a==="update_parameter"){let n=String(i.get("paramKey")??""),s=String(i.get("paramValue")??"");return n?(await t.updateSystemParameter(e,n,s,o),Response.json({success:!0,paramKey:n,paramValue:s})):Response.json({error:"paramKey is required"},{status:400})}if(a==="update_prompt"){let n=String(i.get("templateKey")??""),s=String(i.get("payload")??"{}"),l={templateText:"",modelName:"",temperature:0,maxOutputTokens:0,endpointBaseUrl:null};try{l=JSON.parse(s)}catch{return Response.json({error:"Invalid JSON payload"},{status:400})}if(!n)return Response.json({error:"templateKey is required"},{status:400});try{return await t.updatePromptTemplate(e,n,l,o),Response.json({success:!0,templateKey:n})}catch(d){return Response.json({error:d instanceof Error?d.message:String(d)},{status:400})}}if(a==="reorder_rules"){let n=String(i.get("orderedRuleIds")??"[]"),s=[];try{s=JSON.parse(n)}catch{return Response.json({error:"Invalid orderedRuleIds JSON"},{status:400})}return await t.reorderClassificationRules(e,s,o),Response.json({success:!0,orderedRuleIds:s})}return null}async function Qe(t,e,a,i,o,n){if(a==="retry_job"){let s=String(i.get("fileId")??"");if(!s)return Response.json({error:"fileId is required"},{status:400});try{return await t.retrySyncItem(e,s,o,n),Response.json({success:!0,fileId:s})}catch(l){return Response.json({error:l instanceof Error?l.message:String(l)},{status:400})}}if(a==="retry_all_failed")try{return await t.retryAllFailedSyncItems(e,o,n),Response.json({success:!0,reconciled:!0})}catch(s){return Response.json({error:s instanceof Error?s.message:String(s)},{status:400})}if(a==="reconcile")try{let s=await t.reconcileTriStore(e,n);return Response.json({success:!0,reconciled:!0,result:s})}catch(s){return Response.json({error:s instanceof Error?s.message:String(s)},{status:400})}return null}function $e(t){if(typeof t!="object"||t===null)return"payload must be an object";let e=t;if(typeof e.fileUri!="string"||e.fileUri.trim()==="")return"payload.fileUri is required";if(!B.safeParse(e.confidentialityLevel).success)return`payload.confidentialityLevel must be one of ${B.options.join(", ")}`;let i=e.departmentId;return i!=null&&(typeof i!="number"||!Number.isInteger(i))?"payload.departmentId must be an integer or null":null}async function Ve(t,e,a,i,o,n,s,l){if(a==="ingest_document"){let d=String(i.get("payload")??"");if(!d)return Response.json({error:"payload is required"},{status:400});let m;try{m=JSON.parse(d)}catch{return Response.json({error:"Invalid JSON payload"},{status:400})}let f=$e(m);if(f)return Response.json({error:f},{status:400});let y=m,b=await s(n,y);if(b!==null)return Response.json({error:b},{status:403});try{let u=l?await t.ingestDocument(e,y,o,l):await t.ingestDocument(e,y,o);return Response.json({success:!0,result:u})}catch(u){return Response.json({error:u instanceof Error?u.message:String(u)},{status:400})}}if(a==="inspect_uri"){let d=String(i.get("fileUri")??"").trim();if(!d)return Response.json({error:"fileUri is required"},{status:400});if(!t.inspectFileUri)return Response.json({error:"inspectFileUri is not implemented"},{status:501});try{let m=l?await t.inspectFileUri(e,d,l):await t.inspectFileUri(e,d);return Response.json({success:!0,inspection:m})}catch(m){return Response.json({error:m instanceof Error?m.message:String(m)},{status:400})}}return null}function ct(t){let e=ee(t);return{loader:e.loader,action:e.action,View:J,server:e}}export{J as StorageAdminConsoleView,X as checkAllSystemHealth,He as checkBackendApiHealth,De as checkNeo4jHealth,Oe as checkQdrantHealth,Ue as checkRedisHealth,Fe as checkSqlServerHealth,ct as createStorageAdminApp,ee as createStorageAdminServer};
|
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aiquants/enrichment-react-router",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "React Router (v7 / v8) adapter for storage AI enrichment & knowledge governance admin console.",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"keywords": [
|
|
28
|
+
"react-router",
|
|
29
|
+
"enrichment",
|
|
30
|
+
"governance",
|
|
31
|
+
"storage-admin",
|
|
32
|
+
"console",
|
|
33
|
+
"typescript"
|
|
34
|
+
],
|
|
35
|
+
"author": "AI Quants",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@aiquants/authz-core": "^0.6.1",
|
|
39
|
+
"@aiquants/enrichment-core": "^0.1.1",
|
|
40
|
+
"@aiquants/enrichment-react": "^0.1.0",
|
|
41
|
+
"@aiquants/governance-core": "^0.1.0",
|
|
42
|
+
"@aiquants/governance-react": "^0.1.0",
|
|
43
|
+
"react": ">=18",
|
|
44
|
+
"react-dom": ">=18",
|
|
45
|
+
"react-router": "^7.0.0 || ^8.0.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@aiquants/authz-core": "0.6.1",
|
|
49
|
+
"@aiquants/enrichment-core": "0.1.1",
|
|
50
|
+
"@aiquants/enrichment-react": "0.1.0",
|
|
51
|
+
"@aiquants/governance-core": "0.1.0",
|
|
52
|
+
"@aiquants/governance-react": "0.1.0",
|
|
53
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
54
|
+
"@testing-library/react": "^16.3.2",
|
|
55
|
+
"@testing-library/user-event": "^14.6.1",
|
|
56
|
+
"@types/react": "^19.2.7",
|
|
57
|
+
"@types/react-dom": "^19.2.3",
|
|
58
|
+
"jsdom": "^27.4.0",
|
|
59
|
+
"react": "^19.2.7",
|
|
60
|
+
"react-dom": "^19.2.7",
|
|
61
|
+
"react-router": "^8.3.0",
|
|
62
|
+
"rimraf": "^6.1.2",
|
|
63
|
+
"tsup": "^8.5.1",
|
|
64
|
+
"typescript": "^5.9.3",
|
|
65
|
+
"vitest": "^4.1.10"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"node": ">=18.0.0",
|
|
69
|
+
"pnpm": ">=8.0.0"
|
|
70
|
+
},
|
|
71
|
+
"publishConfig": {
|
|
72
|
+
"access": "public"
|
|
73
|
+
},
|
|
74
|
+
"scripts": {
|
|
75
|
+
"build": "tsup && node ../../.config/scripts/strip-dts-comments.mjs dist",
|
|
76
|
+
"build:watch": "tsup --watch",
|
|
77
|
+
"dev": "tsup --watch",
|
|
78
|
+
"publish:patch": "pnpm run typecheck && pnpm run --if-present test && pnpm version patch --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
79
|
+
"publish:minor": "pnpm run typecheck && pnpm run --if-present test && pnpm version minor --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
80
|
+
"publish:major": "pnpm run typecheck && pnpm run --if-present test && pnpm version major --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
81
|
+
"typecheck": "tsc --noEmit",
|
|
82
|
+
"clean": "rimraf dist",
|
|
83
|
+
"lint": "biome lint src/",
|
|
84
|
+
"check": "biome check src/ tests/",
|
|
85
|
+
"check:fix": "biome check --write src/ tests/",
|
|
86
|
+
"test": "vitest run",
|
|
87
|
+
"test:coverage": "vitest run --coverage"
|
|
88
|
+
}
|
|
89
|
+
}
|