@mindexec/cli 0.2.340 → 0.2.341
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/codex-runtime.js +255 -31
- package/package.json +1 -1
- package/remote-hub.js +80 -2
- package/scripts/remote-fast-live-rate-smoke.mjs +19 -3
- package/scripts/remote-fast-mdm-browser-smoke.mjs +28 -2
- package/scripts/remote-hub-smoke.mjs +32 -2
- package/server.js +1304 -21
- package/wwwroot/_headers +50 -17
- package/wwwroot/assets/AdminDashboardPage-B2vz2Px9.css +1 -0
- package/wwwroot/assets/AdminDashboardPage-DpUfWSRs.js +1 -0
- package/wwwroot/assets/AppSidebar-CBqvLonm.js +1 -0
- package/wwwroot/assets/AuthPages-Cd5fYgU0.js +1 -0
- package/wwwroot/assets/AuthPages-DFGWKWuB.css +1 -0
- package/wwwroot/assets/CodePage-Bncc352E.css +1 -0
- package/wwwroot/assets/CodePage-D9-cUf4A.js +87 -0
- package/wwwroot/assets/CompanyCorePage-ChBnq1ve.css +1 -0
- package/wwwroot/assets/CompanyCorePage-D0byTW77.js +13 -0
- package/wwwroot/assets/ExecutionModePage-DtMDlqYc.js +18 -0
- package/wwwroot/assets/ExecutionModePage-TLuld9l3.css +1 -0
- package/wwwroot/assets/LaunchLeadCapture-CiRI1shz.css +1 -0
- package/wwwroot/assets/LaunchLeadCapture-CqeoHfvb.js +1 -0
- package/wwwroot/assets/MarketingHome-DPzaYzA_.css +1 -0
- package/wwwroot/assets/MarketingHome-DbWyEAya.js +1 -0
- package/wwwroot/assets/MindCanvas-CME1KpAo.js +48 -0
- package/wwwroot/assets/MindCanvas-DiQlUDJu.css +1 -0
- package/wwwroot/assets/PlanMasterPage-CJ36rep-.css +1 -0
- package/wwwroot/assets/PlanMasterPage-mhlZZK19.js +4 -0
- package/wwwroot/assets/PricingPage-Cg_0i_ZR.css +1 -0
- package/wwwroot/assets/PricingPage-zVu8-CrF.js +1 -0
- package/wwwroot/assets/ToolPages-DIB187pZ.css +1 -0
- package/wwwroot/assets/ToolPages-DTSqKzQd.js +28 -0
- package/wwwroot/assets/YouTubeSearchPage-IPPa_BIH.css +1 -0
- package/wwwroot/assets/YouTubeSearchPage-xGiaLNqk.js +4 -0
- package/wwwroot/assets/app-runtime-xD2Z3NdN.js +1 -0
- package/wwwroot/assets/canvas-runtime-D1gfvqKp.js +44 -0
- package/wwwroot/assets/code-agent-runtime-B5PPZd1t.js +74 -0
- package/wwwroot/assets/executionModeSettings-NJqurj-o.js +1 -0
- package/wwwroot/assets/index-CP_xejf2.css +1 -0
- package/wwwroot/assets/index-CZS-9WFu.js +2 -0
- package/wwwroot/assets/marketingTools-DN_rnHeB.js +4 -0
- package/wwwroot/assets/mindCanvasSearchWorker-BzPMsHOB.js +1 -0
- package/wwwroot/assets/mindexecution-mindcanvas.png +0 -0
- package/wwwroot/assets/mindexecution-prod-home-current.png +0 -0
- package/wwwroot/assets/mindexecution-prod-pricing-current.png +0 -0
- package/wwwroot/assets/pricingCheckoutShell-O-DnwmbU.js +1 -0
- package/wwwroot/assets/runtimeSettingsPersistenceProjection-BoNWmYjU.js +1 -0
- package/wwwroot/assets/storage-CGDupGH4.js +1 -0
- package/wwwroot/assets/supabaseAuthAdapter-C3z334Qw.js +44 -0
- package/wwwroot/assets/toolHandoff-D5e5f7t5.js +4 -0
- package/wwwroot/assets/vendor-icons-oiW_NVNO.js +681 -0
- package/wwwroot/assets/vendor-msgpack-BE8aAsr3.js +1 -0
- package/wwwroot/assets/vendor-react-BXzpOyCS.js +40 -0
- package/wwwroot/favicon.svg +7 -0
- package/wwwroot/index.html +22 -736
- package/wwwroot/manifest.webmanifest +18 -21
- package/wwwroot/robots.txt +1 -1
- package/wwwroot/service-worker.js +5 -31
- package/wwwroot/sitemap.xml +21 -9
- package/wwwroot/MindExecution.Web.styles.css +0 -3
- package/wwwroot/_content/MindExecution.Plugins.Admin/css/admin-dashboard.css +0 -546
- package/wwwroot/_content/MindExecution.Plugins.Directory/MindExecution.Plugins.Directory.u7utcng611.bundle.scp.css +0 -7
- package/wwwroot/_content/MindExecution.Plugins.Directory/background.png +0 -0
- package/wwwroot/_content/MindExecution.Plugins.Directory/directory-manager.js +0 -202
- package/wwwroot/_content/MindExecution.Plugins.Directory/exampleJsInterop.js +0 -6
- package/wwwroot/_content/MindExecution.Plugins.YouTube/css/youtube-search.css +0 -251
- package/wwwroot/_content/MindExecution.Shared/MindExecution.Shared.wsano1j4wp.bundle.scp.css +0 -4
- package/wwwroot/_content/MindExecution.Shared/css/admin-dashboard.css +0 -559
- package/wwwroot/_content/MindExecution.Shared/css/app.css +0 -1
- package/wwwroot/_content/MindExecution.Shared/css/mind-map-overrides.css +0 -3705
- package/wwwroot/_content/MindExecution.Shared/fonts/NotoSansKR-Bold.ttf +0 -0
- package/wwwroot/_content/MindExecution.Shared/fonts/NotoSansKR-Regular.ttf +0 -0
- package/wwwroot/_content/MindExecution.Shared/js/agent-visualization.js +0 -359
- package/wwwroot/_content/MindExecution.Shared/js/background-themes.js +0 -1631
- package/wwwroot/_content/MindExecution.Shared/js/code-master.js +0 -8316
- package/wwwroot/_content/MindExecution.Shared/js/file-system-helper.js +0 -639
- package/wwwroot/_content/MindExecution.Shared/js/helpers/InfiniteGridHelper.js +0 -109
- package/wwwroot/_content/MindExecution.Shared/js/marked.min.js +0 -69
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +0 -12909
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js.backup +0 -1059
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +0 -24635
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-dev-guards.js +0 -325
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-dnd.js +0 -1491
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-dnd.js.bak +0 -434
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-glow-shader.js +0 -260
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +0 -7829
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-plan-worker.js +0 -160
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +0 -10400
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-logic-workers.js +0 -977
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-menu-manager.js +0 -1531
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-multi-select.js +0 -1716
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-node-search-worker.js +0 -554
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +0 -4578
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-object-manager.js +0 -489
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-object-manager.js.backup +0 -372
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-pipeline.js +0 -2203
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-text-lod-system.js +0 -646
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-text-overlay-v2.js +0 -4735
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-texture-factory.js +0 -2383
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-texture-factory.js.backup +0 -1258
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-visibility-worker.js +0 -890
- package/wwwroot/_content/MindExecution.Shared/js/mindmap-toolbar.js +0 -639
- package/wwwroot/_content/MindExecution.Shared/js/native-drop-handler.js +0 -170
- package/wwwroot/_content/MindExecution.Shared/js/plan-master.js +0 -788
- package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +0 -90
- package/wwwroot/_content/MindExecution.Shared/js/texture-worker-manager.js +0 -188
- package/wwwroot/_content/MindExecution.Shared/js/texture-worker.js +0 -208
- package/wwwroot/_content/MindExecution.Shared/js/three.min.js +0 -6
- package/wwwroot/_content/MindExecution.Shared/js/titlebar-handler.js +0 -191
- package/wwwroot/_content/MindExecution.Shared/js/token-manager.js +0 -37
- package/wwwroot/_content/MindExecution.Shared/js/token-worker.js +0 -28
- package/wwwroot/_content/MindExecution.Shared/js/troika-bundle.js +0 -5626
- package/wwwroot/_content/MindExecution.Shared/js/troika-bundle.js.map +0 -7
- package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/css/all.min.css +0 -9
- package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-brands-400.ttf +0 -0
- package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-brands-400.woff2 +0 -0
- package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-regular-400.ttf +0 -0
- package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-regular-400.woff2 +0 -0
- package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-solid-900.ttf +0 -0
- package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-solid-900.woff2 +0 -0
- package/wwwroot/_content/MindExecution.Shared/models/all-MiniLM-L6-v2-quantized.onnx +0 -0
- package/wwwroot/_content/MindExecution.Shared/models/vocab.txt +0 -30522
- package/wwwroot/_framework/Google.Protobuf.9h59ukbel7.dll +0 -0
- package/wwwroot/_framework/Markdig.d1j7v41cl1.dll +0 -0
- package/wwwroot/_framework/MessagePack.Annotations.l6qv48kgpt.dll +0 -0
- package/wwwroot/_framework/MessagePack.eqoptzx9d5.dll +0 -0
- package/wwwroot/_framework/Microsoft.AspNetCore.Authorization.k7dsih5y5g.dll +0 -0
- package/wwwroot/_framework/Microsoft.AspNetCore.Components.6nyje9sa0g.dll +0 -0
- package/wwwroot/_framework/Microsoft.AspNetCore.Components.Authorization.iycd6unprw.dll +0 -0
- package/wwwroot/_framework/Microsoft.AspNetCore.Components.Web.487u3twia4.dll +0 -0
- package/wwwroot/_framework/Microsoft.AspNetCore.Components.WebAssembly.d0gcnmlxxz.dll +0 -0
- package/wwwroot/_framework/Microsoft.AspNetCore.Metadata.h4yevl9adi.dll +0 -0
- package/wwwroot/_framework/Microsoft.CSharp.8bsm8vx6su.dll +0 -0
- package/wwwroot/_framework/Microsoft.Data.Sqlite.jdlxgv2jtg.dll +0 -0
- package/wwwroot/_framework/Microsoft.EntityFrameworkCore.4gjazp7kjf.dll +0 -0
- package/wwwroot/_framework/Microsoft.EntityFrameworkCore.Abstractions.gocudnvz7b.dll +0 -0
- package/wwwroot/_framework/Microsoft.EntityFrameworkCore.Relational.lt4rsvinuo.dll +0 -0
- package/wwwroot/_framework/Microsoft.EntityFrameworkCore.Sqlite.69luj0fa9r.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Caching.Abstractions.364t4jh3zz.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Caching.Memory.izlxhpzosu.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Configuration.8zq7hh41o7.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Configuration.Abstractions.8if74zs6ea.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Configuration.Json.duvlngw8i0.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.Abstractions.t2hh9kvx0o.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.n4tg99oy8l.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.DependencyModel.h0d06ixk3e.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Logging.Abstractions.rl32bkx2sd.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Logging.dlht1xei0t.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Options.qeunebioml.dll +0 -0
- package/wwwroot/_framework/Microsoft.Extensions.Primitives.18cr6vnuuz.dll +0 -0
- package/wwwroot/_framework/Microsoft.IO.RecyclableMemoryStream.r915vovvw4.dll +0 -0
- package/wwwroot/_framework/Microsoft.IdentityModel.Abstractions.1ejljk3erv.dll +0 -0
- package/wwwroot/_framework/Microsoft.IdentityModel.JsonWebTokens.1596zr8gne.dll +0 -0
- package/wwwroot/_framework/Microsoft.IdentityModel.Logging.229uyvpgio.dll +0 -0
- package/wwwroot/_framework/Microsoft.IdentityModel.Tokens.9sibtajc9f.dll +0 -0
- package/wwwroot/_framework/Microsoft.JSInterop.WebAssembly.ryia5gxiad.dll +0 -0
- package/wwwroot/_framework/Microsoft.JSInterop.ew9vz9o332.dll +0 -0
- package/wwwroot/_framework/Microsoft.ML.OnnxRuntime.w9deo1m5ss.dll +0 -0
- package/wwwroot/_framework/Microsoft.ML.Tokenizers.cm2vuv2z61.dll +0 -0
- package/wwwroot/_framework/Microsoft.NET.StringTools.3qbrf4v2ki.dll +0 -0
- package/wwwroot/_framework/MimeMapping.og9ys58ylm.dll +0 -0
- package/wwwroot/_framework/MindExecution.Core.y7ffihhajj.dll +0 -0
- package/wwwroot/_framework/MindExecution.Kernel.l5y3qroa7p.dll +0 -0
- package/wwwroot/_framework/MindExecution.Plugins.Admin.uuf238xa0h.dll +0 -0
- package/wwwroot/_framework/MindExecution.Plugins.Business.nyr3v25v48.dll +0 -0
- package/wwwroot/_framework/MindExecution.Plugins.Concept.l9z9tx9svt.dll +0 -0
- package/wwwroot/_framework/MindExecution.Plugins.Directory.ju87t8h3zs.dll +0 -0
- package/wwwroot/_framework/MindExecution.Plugins.PlanMaster.krn3jgvjpa.dll +0 -0
- package/wwwroot/_framework/MindExecution.Plugins.YouTube.5m53srfud6.dll +0 -0
- package/wwwroot/_framework/MindExecution.Shared.ojp3psugsm.dll +0 -0
- package/wwwroot/_framework/MindExecution.Web.82k6ktlkfg.dll +0 -0
- package/wwwroot/_framework/Newtonsoft.Json.a56zs13vug.dll +0 -0
- package/wwwroot/_framework/SQLitePCLRaw.batteries_v2.rrd1nzawpp.dll +0 -0
- package/wwwroot/_framework/SQLitePCLRaw.core.1dxloztpfz.dll +0 -0
- package/wwwroot/_framework/SQLitePCLRaw.provider.e_sqlite3.oekyzl53i1.dll +0 -0
- package/wwwroot/_framework/Supabase.Core.s1pkj4aj0l.dll +0 -0
- package/wwwroot/_framework/Supabase.Functions.qz4nu782sg.dll +0 -0
- package/wwwroot/_framework/Supabase.Gotrue.twah27pkik.dll +0 -0
- package/wwwroot/_framework/Supabase.Postgrest.gmuuv369ih.dll +0 -0
- package/wwwroot/_framework/Supabase.Realtime.ox3kchdy3w.dll +0 -0
- package/wwwroot/_framework/Supabase.Storage.fnjnepaowr.dll +0 -0
- package/wwwroot/_framework/Supabase.azmaw5pgcz.dll +0 -0
- package/wwwroot/_framework/System.Collections.23yxgetbju.dll +0 -0
- package/wwwroot/_framework/System.Collections.Concurrent.vow3rm1dku.dll +0 -0
- package/wwwroot/_framework/System.Collections.Immutable.ap9596utv5.dll +0 -0
- package/wwwroot/_framework/System.Collections.NonGeneric.npjkaz40oc.dll +0 -0
- package/wwwroot/_framework/System.Collections.Specialized.ugkjbs6p02.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.Annotations.clwo0z2oyu.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.Primitives.end4v0xe2c.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.TypeConverter.tgtp5sm4iv.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.wupoltkk1t.dll +0 -0
- package/wwwroot/_framework/System.Console.9dik0wogo2.dll +0 -0
- package/wwwroot/_framework/System.Data.Common.4v8jejsiu0.dll +0 -0
- package/wwwroot/_framework/System.Diagnostics.DiagnosticSource.e2q75ondtq.dll +0 -0
- package/wwwroot/_framework/System.Diagnostics.Process.9736yjnxs8.dll +0 -0
- package/wwwroot/_framework/System.Diagnostics.TraceSource.h9al53gbbw.dll +0 -0
- package/wwwroot/_framework/System.Diagnostics.Tracing.h4bcp2fo98.dll +0 -0
- package/wwwroot/_framework/System.Drawing.64oovy8qts.dll +0 -0
- package/wwwroot/_framework/System.Drawing.Primitives.o6jiqpgbgl.dll +0 -0
- package/wwwroot/_framework/System.Formats.Asn1.rylx5ipd40.dll +0 -0
- package/wwwroot/_framework/System.IO.Compression.iceabaupns.dll +0 -0
- package/wwwroot/_framework/System.IO.Pipelines.uw8csd3mlz.dll +0 -0
- package/wwwroot/_framework/System.IdentityModel.Tokens.Jwt.t67es60z5b.dll +0 -0
- package/wwwroot/_framework/System.Linq.Expressions.ty95ava37f.dll +0 -0
- package/wwwroot/_framework/System.Linq.Queryable.hs2195jrwy.dll +0 -0
- package/wwwroot/_framework/System.Linq.hssodjwmlf.dll +0 -0
- package/wwwroot/_framework/System.Memory.1k78n7wdxb.dll +0 -0
- package/wwwroot/_framework/System.Net.Http.3br8rfql4c.dll +0 -0
- package/wwwroot/_framework/System.Net.Http.Json.860wbh17d8.dll +0 -0
- package/wwwroot/_framework/System.Net.NetworkInformation.e3wr00853o.dll +0 -0
- package/wwwroot/_framework/System.Net.Ping.r5cw4mf1a4.dll +0 -0
- package/wwwroot/_framework/System.Net.Primitives.ksxwiwlvhu.dll +0 -0
- package/wwwroot/_framework/System.Net.WebSockets.6rt3n3gl2q.dll +0 -0
- package/wwwroot/_framework/System.Net.WebSockets.Client.z3usrzo7rz.dll +0 -0
- package/wwwroot/_framework/System.Numerics.Tensors.0c7z4mt3on.dll +0 -0
- package/wwwroot/_framework/System.Numerics.Vectors.lbdzx8reja.dll +0 -0
- package/wwwroot/_framework/System.ObjectModel.yct1gdirzf.dll +0 -0
- package/wwwroot/_framework/System.Private.CoreLib.c1dbswx1b2.dll +0 -0
- package/wwwroot/_framework/System.Private.Uri.zp9kmg0z93.dll +0 -0
- package/wwwroot/_framework/System.Private.Xml.Linq.lgv2n0akl4.dll +0 -0
- package/wwwroot/_framework/System.Private.Xml.dpsk8g304y.dll +0 -0
- package/wwwroot/_framework/System.Reactive.t3fuon548l.dll +0 -0
- package/wwwroot/_framework/System.Reflection.Emit.ILGeneration.1tcuz2cmbk.dll +0 -0
- package/wwwroot/_framework/System.Reflection.Emit.Lightweight.ddt2wylovg.dll +0 -0
- package/wwwroot/_framework/System.Reflection.Emit.d8vkadiwhg.dll +0 -0
- package/wwwroot/_framework/System.Reflection.Primitives.cpsl71xd1z.dll +0 -0
- package/wwwroot/_framework/System.Runtime.InteropServices.31vjgsfk1o.dll +0 -0
- package/wwwroot/_framework/System.Runtime.InteropServices.JavaScript.pn2wvizzet.dll +0 -0
- package/wwwroot/_framework/System.Runtime.InteropServices.RuntimeInformation.l5rk496q70.dll +0 -0
- package/wwwroot/_framework/System.Runtime.Intrinsics.0zee9qcqfy.dll +0 -0
- package/wwwroot/_framework/System.Runtime.Loader.xw2jr9wl92.dll +0 -0
- package/wwwroot/_framework/System.Runtime.Numerics.ezj1dfyvbj.dll +0 -0
- package/wwwroot/_framework/System.Runtime.Serialization.Formatters.0y019e9zkr.dll +0 -0
- package/wwwroot/_framework/System.Runtime.Serialization.Primitives.bia5wb62c8.dll +0 -0
- package/wwwroot/_framework/System.Runtime.h9cduidfkh.dll +0 -0
- package/wwwroot/_framework/System.Security.Claims.2r18wim2rl.dll +0 -0
- package/wwwroot/_framework/System.Security.Cryptography.qqgybpoucx.dll +0 -0
- package/wwwroot/_framework/System.Text.Encoding.Extensions.9t3hs6kyll.dll +0 -0
- package/wwwroot/_framework/System.Text.Encodings.Web.wftjfh2crk.dll +0 -0
- package/wwwroot/_framework/System.Text.Json.0v0qgmri0w.dll +0 -0
- package/wwwroot/_framework/System.Text.RegularExpressions.cvkox11l6l.dll +0 -0
- package/wwwroot/_framework/System.Threading.Channels.419493szqu.dll +0 -0
- package/wwwroot/_framework/System.Threading.Thread.xhmys87xh5.dll +0 -0
- package/wwwroot/_framework/System.Threading.b66vzsz9g1.dll +0 -0
- package/wwwroot/_framework/System.Transactions.Local.7zfffdvnwf.dll +0 -0
- package/wwwroot/_framework/System.Web.HttpUtility.9up6xfbtuq.dll +0 -0
- package/wwwroot/_framework/System.Xml.Linq.n5rzv9nbf7.dll +0 -0
- package/wwwroot/_framework/System.Xml.ReaderWriter.ag8pilllob.dll +0 -0
- package/wwwroot/_framework/System.Xml.XDocument.sn51jas17n.dll +0 -0
- package/wwwroot/_framework/System.brmz7yk5qh.dll +0 -0
- package/wwwroot/_framework/Websocket.Client.vapounvmnl.dll +0 -0
- package/wwwroot/_framework/blazor.boot.json +0 -305
- package/wwwroot/_framework/blazor.webassembly.js +0 -1
- package/wwwroot/_framework/dotnet.js +0 -4
- package/wwwroot/_framework/dotnet.native.boem75ye5i.wasm +0 -0
- package/wwwroot/_framework/dotnet.native.qc8g39g30v.js +0 -16
- package/wwwroot/_framework/dotnet.runtime.opaiwunc3t.js +0 -4
- package/wwwroot/_framework/icudt_CJK.tjcz0u77k5.dat +0 -0
- package/wwwroot/_framework/icudt_EFIGS.tptq2av103.dat +0 -0
- package/wwwroot/_framework/icudt_no_CJK.lfu7j35m59.dat +0 -0
- package/wwwroot/_framework/netstandard.yvr3prsx0x.dll +0 -0
- package/wwwroot/appsettings.json +0 -83
- package/wwwroot/icon-192.png +0 -0
- package/wwwroot/icon-512.png +0 -0
- package/wwwroot/js/marketing-tool.js +0 -180
- package/wwwroot/service-worker-assets.js +0 -857
package/server.js
CHANGED
|
@@ -2138,6 +2138,13 @@ const PROTECTED_BRIDGE_ROUTES = [
|
|
|
2138
2138
|
{ method: 'POST', exact: '/api/dir/delete' },
|
|
2139
2139
|
{ method: 'POST', prefix: '/api/assets/' },
|
|
2140
2140
|
{ method: 'POST', exact: '/api/local-files/register' },
|
|
2141
|
+
{ method: 'POST', exact: '/api/evidence/save' },
|
|
2142
|
+
{ method: 'POST', exact: '/api/concept/define-composite' },
|
|
2143
|
+
{ method: 'GET', exact: '/api/concept/status' },
|
|
2144
|
+
{ method: 'GET', exact: '/api/concept/row' },
|
|
2145
|
+
{ method: 'GET', exact: '/api/concept/sqlite/row' },
|
|
2146
|
+
{ method: 'GET', exact: '/api/concept/embed/readiness' },
|
|
2147
|
+
{ method: 'POST', exact: '/api/concept/embed' },
|
|
2141
2148
|
{ method: 'POST', prefix: '/api/browser/act' },
|
|
2142
2149
|
{ method: 'GET', prefix: '/api/company-core/' },
|
|
2143
2150
|
{ method: 'POST', prefix: '/api/company-core/' },
|
|
@@ -2661,6 +2668,39 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
|
2661
2668
|
}
|
|
2662
2669
|
|
|
2663
2670
|
const frame = frameEvent.frame || {};
|
|
2671
|
+
const droppedByAgent = Number(frame.droppedByAgent ?? frameEvent.droppedByAgent ?? 0);
|
|
2672
|
+
const dirtyRectSource = frame.dirtyRectCount
|
|
2673
|
+
?? frame.dirtyRegionCount
|
|
2674
|
+
?? frameEvent.dirtyRectCount
|
|
2675
|
+
?? frameEvent.dirtyRegionCount
|
|
2676
|
+
?? (Array.isArray(frame.dirtyRects) ? frame.dirtyRects.length : undefined)
|
|
2677
|
+
?? (Array.isArray(frameEvent.dirtyRects) ? frameEvent.dirtyRects.length : undefined)
|
|
2678
|
+
?? 0;
|
|
2679
|
+
const dirtyRectCount = Number(dirtyRectSource);
|
|
2680
|
+
const dirtyRatioSource = frame.dirtyPixelRatio
|
|
2681
|
+
?? frame.dirtyRatio
|
|
2682
|
+
?? frame.dirtyAreaRatio
|
|
2683
|
+
?? frame.changedPixelRatio
|
|
2684
|
+
?? frameEvent.dirtyPixelRatio
|
|
2685
|
+
?? frameEvent.dirtyRatio
|
|
2686
|
+
?? frameEvent.dirtyAreaRatio
|
|
2687
|
+
?? frameEvent.changedPixelRatio
|
|
2688
|
+
?? 0;
|
|
2689
|
+
const dirtyRatioNumber = Number(dirtyRatioSource);
|
|
2690
|
+
const normalizedDirtyPixelRatio = Number.isFinite(dirtyRatioNumber) && dirtyRatioNumber >= 0
|
|
2691
|
+
? dirtyRatioNumber <= 1
|
|
2692
|
+
? dirtyRatioNumber
|
|
2693
|
+
: dirtyRatioNumber <= 100
|
|
2694
|
+
? dirtyRatioNumber / 100
|
|
2695
|
+
: 1
|
|
2696
|
+
: 0;
|
|
2697
|
+
const deltaValue = frame.deltaEncoded ?? frame.isDeltaEncoded ?? frame.deltaFrame
|
|
2698
|
+
?? frameEvent.deltaEncoded ?? frameEvent.isDeltaEncoded ?? frameEvent.deltaFrame;
|
|
2699
|
+
const deltaEncoded = typeof deltaValue === 'boolean'
|
|
2700
|
+
? deltaValue
|
|
2701
|
+
: typeof deltaValue === 'number'
|
|
2702
|
+
? deltaValue > 0
|
|
2703
|
+
: /^(1|true|yes|on|delta)$/i.test(String(deltaValue || '').trim());
|
|
2664
2704
|
const metadata = {
|
|
2665
2705
|
type: 'remote.frame.binary',
|
|
2666
2706
|
kind: frameEvent.kind || 'live',
|
|
@@ -2678,7 +2718,16 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
|
2678
2718
|
transport: frame.transport || '',
|
|
2679
2719
|
contentHash: frame.contentHash || '',
|
|
2680
2720
|
captureMs: Number(frame.captureMs || 0) || 0,
|
|
2681
|
-
sameContentStreak: Number(frame.sameContentStreak || 0) || 0
|
|
2721
|
+
sameContentStreak: Number(frame.sameContentStreak || 0) || 0,
|
|
2722
|
+
droppedByAgent: Number.isFinite(droppedByAgent) && droppedByAgent >= 0
|
|
2723
|
+
? Math.round(droppedByAgent)
|
|
2724
|
+
: 0,
|
|
2725
|
+
dirtyRectCount: Number.isFinite(dirtyRectCount) && dirtyRectCount >= 0
|
|
2726
|
+
? Math.round(dirtyRectCount)
|
|
2727
|
+
: 0,
|
|
2728
|
+
dirtyPixelRatio: normalizedDirtyPixelRatio,
|
|
2729
|
+
codec: String(frame.codec || frame.encoder || frame.encoding || frameEvent.codec || frameEvent.encoder || frameEvent.encoding || '').slice(0, 80),
|
|
2730
|
+
deltaEncoded
|
|
2682
2731
|
};
|
|
2683
2732
|
const metaBuffer = Buffer.from(JSON.stringify(metadata), 'utf8');
|
|
2684
2733
|
const header = Buffer.allocUnsafe(4);
|
|
@@ -10958,7 +11007,7 @@ function scoreSearchResult(query, item) {
|
|
|
10958
11007
|
return score;
|
|
10959
11008
|
}
|
|
10960
11009
|
|
|
10961
|
-
function filterSearchResults(query, items, maxResults) {
|
|
11010
|
+
function filterSearchResults(query, items, maxResults) {
|
|
10962
11011
|
const clampedMax = Math.max(1, Math.min(Number(maxResults) || 5, 8));
|
|
10963
11012
|
const list = Array.isArray(items) ? items : [];
|
|
10964
11013
|
if (!requiresSearchRelevanceFilter(query)) {
|
|
@@ -10969,10 +11018,29 @@ function filterSearchResults(query, items, maxResults) {
|
|
|
10969
11018
|
.map(item => ({ item, score: scoreSearchResult(query, item) }))
|
|
10970
11019
|
.filter(entry => entry.score > 0)
|
|
10971
11020
|
.sort((a, b) => b.score - a.score)
|
|
10972
|
-
.map(entry => entry.item)
|
|
10973
|
-
.slice(0, clampedMax);
|
|
10974
|
-
}
|
|
10975
|
-
|
|
11021
|
+
.map(entry => entry.item)
|
|
11022
|
+
.slice(0, clampedMax);
|
|
11023
|
+
}
|
|
11024
|
+
|
|
11025
|
+
function extractDirectSearchUrl(query) {
|
|
11026
|
+
const match = String(query || '').match(/https?:\/\/[^\s"'<>),]+/i);
|
|
11027
|
+
if (!match) {
|
|
11028
|
+
return '';
|
|
11029
|
+
}
|
|
11030
|
+
|
|
11031
|
+
try {
|
|
11032
|
+
const parsed = new URL(match[0]);
|
|
11033
|
+
if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
|
|
11034
|
+
return parsed.toString();
|
|
11035
|
+
}
|
|
11036
|
+
} catch {
|
|
11037
|
+
return '';
|
|
11038
|
+
}
|
|
11039
|
+
|
|
11040
|
+
return '';
|
|
11041
|
+
}
|
|
11042
|
+
|
|
11043
|
+
async function searchBing(query, maxResults = 5) {
|
|
10976
11044
|
const clampedMax = Math.max(1, Math.min(Number(maxResults) || 5, 8));
|
|
10977
11045
|
const searchQuery = expandSearchQuery(query);
|
|
10978
11046
|
const url = `https://www.bing.com/search?q=${encodeURIComponent(searchQuery)}`;
|
|
@@ -10998,8 +11066,22 @@ async function searchBing(query, maxResults = 5) {
|
|
|
10998
11066
|
};
|
|
10999
11067
|
}
|
|
11000
11068
|
|
|
11001
|
-
async function searchWeb(query, maxResults = 5) {
|
|
11069
|
+
async function searchWeb(query, maxResults = 5) {
|
|
11002
11070
|
const searchQuery = expandSearchQuery(query);
|
|
11071
|
+
const directUrl = extractDirectSearchUrl(searchQuery);
|
|
11072
|
+
if (directUrl) {
|
|
11073
|
+
return {
|
|
11074
|
+
query: searchQuery,
|
|
11075
|
+
source: 'direct-url',
|
|
11076
|
+
retrievedAt: new Date().toISOString(),
|
|
11077
|
+
items: [{
|
|
11078
|
+
title: 'Direct URL evidence',
|
|
11079
|
+
url: directUrl,
|
|
11080
|
+
snippet: `Direct URL extracted from the WebResearch query: ${directUrl}`
|
|
11081
|
+
}]
|
|
11082
|
+
};
|
|
11083
|
+
}
|
|
11084
|
+
|
|
11003
11085
|
const providers = [
|
|
11004
11086
|
['duckduckgo', searchDuckDuckGo],
|
|
11005
11087
|
['brave', searchBrave],
|
|
@@ -11034,7 +11116,7 @@ async function searchWeb(query, maxResults = 5) {
|
|
|
11034
11116
|
throw error;
|
|
11035
11117
|
}
|
|
11036
11118
|
|
|
11037
|
-
async function fetchWebPage(url, maxChars = 12000) {
|
|
11119
|
+
async function fetchWebPage(url, maxChars = 12000) {
|
|
11038
11120
|
let parsedUrl;
|
|
11039
11121
|
try {
|
|
11040
11122
|
parsedUrl = new URL(url);
|
|
@@ -11083,10 +11165,1104 @@ async function fetchWebPage(url, maxChars = 12000) {
|
|
|
11083
11165
|
contentType,
|
|
11084
11166
|
truncated,
|
|
11085
11167
|
retrievedAt: new Date().toISOString()
|
|
11086
|
-
};
|
|
11087
|
-
}
|
|
11088
|
-
|
|
11089
|
-
function
|
|
11168
|
+
};
|
|
11169
|
+
}
|
|
11170
|
+
|
|
11171
|
+
function clampEvidenceText(value, maxLength = 4000) {
|
|
11172
|
+
const text = String(value ?? '').replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim();
|
|
11173
|
+
if (!text) {
|
|
11174
|
+
return '';
|
|
11175
|
+
}
|
|
11176
|
+
return text.length <= maxLength ? text : `${text.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
|
|
11177
|
+
}
|
|
11178
|
+
|
|
11179
|
+
function evidenceArray(value, maxItems = 12, maxItemLength = 500) {
|
|
11180
|
+
const source = Array.isArray(value) ? value : [];
|
|
11181
|
+
const seen = new Set();
|
|
11182
|
+
const items = [];
|
|
11183
|
+
for (const item of source) {
|
|
11184
|
+
const text = clampEvidenceText(item, maxItemLength);
|
|
11185
|
+
const key = text.toLowerCase();
|
|
11186
|
+
if (!text || seen.has(key)) {
|
|
11187
|
+
continue;
|
|
11188
|
+
}
|
|
11189
|
+
seen.add(key);
|
|
11190
|
+
items.push(text);
|
|
11191
|
+
if (items.length >= maxItems) {
|
|
11192
|
+
break;
|
|
11193
|
+
}
|
|
11194
|
+
}
|
|
11195
|
+
return items;
|
|
11196
|
+
}
|
|
11197
|
+
|
|
11198
|
+
function slugifyEvidence(value, maxLength = 56) {
|
|
11199
|
+
const slug = String(value || 'evidence')
|
|
11200
|
+
.normalize('NFKD')
|
|
11201
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
11202
|
+
.replace(/[^a-zA-Z0-9]+/g, '-')
|
|
11203
|
+
.replace(/^-+|-+$/g, '')
|
|
11204
|
+
.toLowerCase();
|
|
11205
|
+
return (slug || 'evidence').slice(0, maxLength).replace(/-+$/g, '') || 'evidence';
|
|
11206
|
+
}
|
|
11207
|
+
|
|
11208
|
+
function safeEvidenceDirectory(baseDir, relativeDirectory) {
|
|
11209
|
+
const base = path.resolve(baseDir);
|
|
11210
|
+
const raw = String(relativeDirectory || '').trim();
|
|
11211
|
+
if (!raw) {
|
|
11212
|
+
return base;
|
|
11213
|
+
}
|
|
11214
|
+
|
|
11215
|
+
const safeSegments = raw
|
|
11216
|
+
.replaceAll('\\', '/')
|
|
11217
|
+
.split('/')
|
|
11218
|
+
.map(segment => slugifyEvidence(segment, 40))
|
|
11219
|
+
.filter(Boolean)
|
|
11220
|
+
.slice(0, 4);
|
|
11221
|
+
const target = path.resolve(base, ...safeSegments);
|
|
11222
|
+
if (!isPathWithin(base, target)) {
|
|
11223
|
+
const err = new Error('Evidence directory must stay under the evidence cache.');
|
|
11224
|
+
err.statusCode = 400;
|
|
11225
|
+
throw err;
|
|
11226
|
+
}
|
|
11227
|
+
return target;
|
|
11228
|
+
}
|
|
11229
|
+
|
|
11230
|
+
function normalizeEvidenceUrl(value) {
|
|
11231
|
+
const text = clampEvidenceText(value, 1200);
|
|
11232
|
+
if (!text) {
|
|
11233
|
+
return '';
|
|
11234
|
+
}
|
|
11235
|
+
|
|
11236
|
+
try {
|
|
11237
|
+
const parsed = new URL(text);
|
|
11238
|
+
if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
|
|
11239
|
+
return parsed.toString();
|
|
11240
|
+
}
|
|
11241
|
+
} catch {
|
|
11242
|
+
// SourceUrl is optional. Invalid values are ignored instead of persisted.
|
|
11243
|
+
}
|
|
11244
|
+
|
|
11245
|
+
return '';
|
|
11246
|
+
}
|
|
11247
|
+
|
|
11248
|
+
function normalizeStructuredEvidence(value) {
|
|
11249
|
+
const source = value && typeof value === 'object' ? value : {};
|
|
11250
|
+
const sourceUrl = normalizeEvidenceUrl(source.sourceUrl || source.SourceUrl);
|
|
11251
|
+
const sourcePath = clampEvidenceText(source.sourcePath || source.SourcePath, 1200);
|
|
11252
|
+
return {
|
|
11253
|
+
Schema: clampEvidenceText(source.schema || source.Schema || 'facts', 80) || 'facts',
|
|
11254
|
+
SourceType: clampEvidenceText(source.sourceType || source.SourceType || 'web', 80) || 'web',
|
|
11255
|
+
SourceUrl: sourceUrl || undefined,
|
|
11256
|
+
SourcePath: sourcePath || undefined,
|
|
11257
|
+
Title: clampEvidenceText(source.title || source.Title, 240),
|
|
11258
|
+
Summary: clampEvidenceText(source.summary || source.Summary, 2000),
|
|
11259
|
+
Facts: evidenceArray(source.facts || source.Facts, 16, 600),
|
|
11260
|
+
Dates: evidenceArray(source.dates || source.Dates, 12, 120),
|
|
11261
|
+
Links: evidenceArray(source.links || source.Links, 16, 1200),
|
|
11262
|
+
Prices: evidenceArray(source.prices || source.Prices, 12, 120),
|
|
11263
|
+
CharCount: Math.max(0, Math.min(Number(source.charCount || source.CharCount || 0) || 0, 1000000)),
|
|
11264
|
+
ExtractedAtUtc: clampEvidenceText(source.structuredAt || source.extractedAt || source.ExtractedAtUtc, 80) || new Date().toISOString()
|
|
11265
|
+
};
|
|
11266
|
+
}
|
|
11267
|
+
|
|
11268
|
+
function normalizeEvidenceMetadata(value, kind, sourceUrl) {
|
|
11269
|
+
const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
11270
|
+
const metadata = {};
|
|
11271
|
+
for (const [key, item] of Object.entries(source)) {
|
|
11272
|
+
const safeKey = String(key || '').replace(/[^a-zA-Z0-9_.:-]/g, '').slice(0, 80);
|
|
11273
|
+
const safeValue = clampEvidenceText(item, 500);
|
|
11274
|
+
if (safeKey && safeValue) {
|
|
11275
|
+
metadata[safeKey] = safeValue;
|
|
11276
|
+
}
|
|
11277
|
+
}
|
|
11278
|
+
|
|
11279
|
+
if (!metadata.kind) {
|
|
11280
|
+
metadata.kind = kind;
|
|
11281
|
+
}
|
|
11282
|
+
|
|
11283
|
+
if (sourceUrl) {
|
|
11284
|
+
try {
|
|
11285
|
+
metadata.sourceHost = new URL(sourceUrl).host;
|
|
11286
|
+
} catch {
|
|
11287
|
+
metadata.sourceHost = sourceUrl;
|
|
11288
|
+
}
|
|
11289
|
+
}
|
|
11290
|
+
|
|
11291
|
+
return metadata;
|
|
11292
|
+
}
|
|
11293
|
+
|
|
11294
|
+
function buildEvidenceResponse(record) {
|
|
11295
|
+
return {
|
|
11296
|
+
success: true,
|
|
11297
|
+
id: record.Id,
|
|
11298
|
+
kind: record.Kind,
|
|
11299
|
+
title: record.Title,
|
|
11300
|
+
query: record.Query,
|
|
11301
|
+
sourceUrl: record.SourceUrl,
|
|
11302
|
+
sourcePath: record.SourcePath,
|
|
11303
|
+
excerpt: record.Excerpt,
|
|
11304
|
+
notes: record.Notes,
|
|
11305
|
+
path: record.Path,
|
|
11306
|
+
sha256: record.Sha256,
|
|
11307
|
+
capturedAt: record.CapturedAtUtc,
|
|
11308
|
+
metadata: record.Metadata,
|
|
11309
|
+
structured: record.Structured
|
|
11310
|
+
};
|
|
11311
|
+
}
|
|
11312
|
+
|
|
11313
|
+
async function saveEvidenceRecord(request = {}) {
|
|
11314
|
+
const capturedAt = new Date();
|
|
11315
|
+
const structured = normalizeStructuredEvidence(request.structured || request.Structured);
|
|
11316
|
+
const kind = clampEvidenceText(request.kind || request.Kind || 'evidence', 120) || 'evidence';
|
|
11317
|
+
const sourceUrl = normalizeEvidenceUrl(request.sourceUrl || request.SourceUrl) || structured.SourceUrl || '';
|
|
11318
|
+
const title = clampEvidenceText(request.title || request.Title || structured.Title || request.query || request.Query || sourceUrl || kind, 240);
|
|
11319
|
+
const query = clampEvidenceText(request.query || request.Query, 500);
|
|
11320
|
+
const sourcePath = clampEvidenceText(request.sourcePath || request.SourcePath || structured.SourcePath, 1200);
|
|
11321
|
+
const excerpt = clampEvidenceText(request.excerpt || request.Excerpt || structured.Summary, 2400);
|
|
11322
|
+
const notes = clampEvidenceText(request.notes || request.Notes, 2000);
|
|
11323
|
+
const metadata = normalizeEvidenceMetadata(request.metadata || request.Metadata, kind, sourceUrl);
|
|
11324
|
+
const baseEvidenceDir = path.join(getAiPath(), 'external', 'evidence');
|
|
11325
|
+
const targetDir = safeEvidenceDirectory(baseEvidenceDir, request.relativeDirectory || request.RelativeDirectory);
|
|
11326
|
+
const slugSource = title || query || sourceUrl || sourcePath || kind || 'evidence';
|
|
11327
|
+
const fileName = `${capturedAt.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z')}-${slugifyEvidence(slugSource)}.json`;
|
|
11328
|
+
const fullPath = path.resolve(targetDir, fileName);
|
|
11329
|
+
if (!isPathWithin(baseEvidenceDir, fullPath)) {
|
|
11330
|
+
const err = new Error('Evidence path must stay under the evidence cache.');
|
|
11331
|
+
err.statusCode = 400;
|
|
11332
|
+
throw err;
|
|
11333
|
+
}
|
|
11334
|
+
|
|
11335
|
+
const relativePath = normalizePathForClient(path.relative(workspacePath, fullPath));
|
|
11336
|
+
const id = `evidence-${capturedAt.toISOString().replace(/[-:T.]/g, '').slice(0, 14)}-${crypto.randomUUID().replace(/-/g, '').slice(0, 8)}`;
|
|
11337
|
+
const record = {
|
|
11338
|
+
Id: id,
|
|
11339
|
+
Kind: kind,
|
|
11340
|
+
Title: title,
|
|
11341
|
+
Query: query || undefined,
|
|
11342
|
+
SourceUrl: sourceUrl || undefined,
|
|
11343
|
+
SourcePath: sourcePath || undefined,
|
|
11344
|
+
Excerpt: excerpt,
|
|
11345
|
+
Notes: notes || undefined,
|
|
11346
|
+
CapturedAtUtc: capturedAt.toISOString(),
|
|
11347
|
+
Structured: structured,
|
|
11348
|
+
Metadata: metadata,
|
|
11349
|
+
Path: relativePath
|
|
11350
|
+
};
|
|
11351
|
+
|
|
11352
|
+
const unsignedJson = JSON.stringify(record, null, 2);
|
|
11353
|
+
record.Sha256 = crypto.createHash('sha256').update(unsignedJson, 'utf8').digest('hex');
|
|
11354
|
+
const finalJson = `${JSON.stringify(record, null, 2)}\n`;
|
|
11355
|
+
await writeFileAtomically(fullPath, finalJson, 'utf8');
|
|
11356
|
+
return record;
|
|
11357
|
+
}
|
|
11358
|
+
|
|
11359
|
+
const CONCEPT_HASH_ALGORITHM = 'xxHash64(seed=0, utf8-trim)';
|
|
11360
|
+
const CONCEPT_EMBEDDING_MODEL = 'local-xxhash64-preview-16';
|
|
11361
|
+
const CONCEPT_EMBED_LIVE_CONFIRM_VALUE = 'I_UNDERSTAND_THIS_CALLS_EMBEDDING_PROVIDER';
|
|
11362
|
+
const CONCEPT_U64_MASK = (1n << 64n) - 1n;
|
|
11363
|
+
const CONCEPT_I64_MAX = (1n << 63n) - 1n;
|
|
11364
|
+
const CONCEPT_U64_SIZE = 1n << 64n;
|
|
11365
|
+
const CONCEPT_PRIME64_1 = 11400714785074694791n;
|
|
11366
|
+
const CONCEPT_PRIME64_2 = 14029467366897019727n;
|
|
11367
|
+
const CONCEPT_PRIME64_3 = 1609587929392839161n;
|
|
11368
|
+
const CONCEPT_PRIME64_4 = 9650029242287828579n;
|
|
11369
|
+
const CONCEPT_PRIME64_5 = 2870177450012600261n;
|
|
11370
|
+
let nodeSqliteModulePromise = null;
|
|
11371
|
+
|
|
11372
|
+
function conceptU64(value) {
|
|
11373
|
+
return BigInt.asUintN(64, value);
|
|
11374
|
+
}
|
|
11375
|
+
|
|
11376
|
+
function conceptRotateLeft(value, count) {
|
|
11377
|
+
const shift = BigInt(count);
|
|
11378
|
+
return conceptU64((conceptU64(value) << shift) | (conceptU64(value) >> (64n - shift)));
|
|
11379
|
+
}
|
|
11380
|
+
|
|
11381
|
+
function conceptReadUInt32LE(data, offset) {
|
|
11382
|
+
return Number(data[offset])
|
|
11383
|
+
| (Number(data[offset + 1]) << 8)
|
|
11384
|
+
| (Number(data[offset + 2]) << 16)
|
|
11385
|
+
| (Number(data[offset + 3]) << 24);
|
|
11386
|
+
}
|
|
11387
|
+
|
|
11388
|
+
function conceptReadUInt64LE(data, offset) {
|
|
11389
|
+
let value = 0n;
|
|
11390
|
+
for (let index = 0; index < 8; index += 1) {
|
|
11391
|
+
value |= BigInt(data[offset + index]) << BigInt(index * 8);
|
|
11392
|
+
}
|
|
11393
|
+
return conceptU64(value);
|
|
11394
|
+
}
|
|
11395
|
+
|
|
11396
|
+
function conceptXxHash64Round(acc, input) {
|
|
11397
|
+
let value = conceptU64(acc + conceptU64(input * CONCEPT_PRIME64_2));
|
|
11398
|
+
value = conceptRotateLeft(value, 31);
|
|
11399
|
+
return conceptU64(value * CONCEPT_PRIME64_1);
|
|
11400
|
+
}
|
|
11401
|
+
|
|
11402
|
+
function conceptXxHash64MergeRound(acc, value) {
|
|
11403
|
+
let next = conceptU64(acc ^ conceptXxHash64Round(0n, value));
|
|
11404
|
+
next = conceptU64(next * CONCEPT_PRIME64_1 + CONCEPT_PRIME64_4);
|
|
11405
|
+
return next;
|
|
11406
|
+
}
|
|
11407
|
+
|
|
11408
|
+
function conceptXxHash64(bytes, seed = 0n) {
|
|
11409
|
+
const data = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes || []);
|
|
11410
|
+
const len = data.length;
|
|
11411
|
+
let index = 0;
|
|
11412
|
+
let h64;
|
|
11413
|
+
|
|
11414
|
+
if (len >= 32) {
|
|
11415
|
+
let v1 = conceptU64(seed + CONCEPT_PRIME64_1 + CONCEPT_PRIME64_2);
|
|
11416
|
+
let v2 = conceptU64(seed + CONCEPT_PRIME64_2);
|
|
11417
|
+
let v3 = conceptU64(seed);
|
|
11418
|
+
let v4 = conceptU64(seed - CONCEPT_PRIME64_1);
|
|
11419
|
+
const limit = len - 32;
|
|
11420
|
+
while (index <= limit) {
|
|
11421
|
+
v1 = conceptXxHash64Round(v1, conceptReadUInt64LE(data, index)); index += 8;
|
|
11422
|
+
v2 = conceptXxHash64Round(v2, conceptReadUInt64LE(data, index)); index += 8;
|
|
11423
|
+
v3 = conceptXxHash64Round(v3, conceptReadUInt64LE(data, index)); index += 8;
|
|
11424
|
+
v4 = conceptXxHash64Round(v4, conceptReadUInt64LE(data, index)); index += 8;
|
|
11425
|
+
}
|
|
11426
|
+
h64 = conceptU64(
|
|
11427
|
+
conceptRotateLeft(v1, 1)
|
|
11428
|
+
+ conceptRotateLeft(v2, 7)
|
|
11429
|
+
+ conceptRotateLeft(v3, 12)
|
|
11430
|
+
+ conceptRotateLeft(v4, 18)
|
|
11431
|
+
);
|
|
11432
|
+
h64 = conceptXxHash64MergeRound(h64, v1);
|
|
11433
|
+
h64 = conceptXxHash64MergeRound(h64, v2);
|
|
11434
|
+
h64 = conceptXxHash64MergeRound(h64, v3);
|
|
11435
|
+
h64 = conceptXxHash64MergeRound(h64, v4);
|
|
11436
|
+
} else {
|
|
11437
|
+
h64 = conceptU64(seed + CONCEPT_PRIME64_5);
|
|
11438
|
+
}
|
|
11439
|
+
|
|
11440
|
+
h64 = conceptU64(h64 + BigInt(len));
|
|
11441
|
+
while (index <= len - 8) {
|
|
11442
|
+
const k1 = conceptXxHash64Round(0n, conceptReadUInt64LE(data, index));
|
|
11443
|
+
h64 = conceptU64(h64 ^ k1);
|
|
11444
|
+
h64 = conceptU64(conceptRotateLeft(h64, 27) * CONCEPT_PRIME64_1 + CONCEPT_PRIME64_4);
|
|
11445
|
+
index += 8;
|
|
11446
|
+
}
|
|
11447
|
+
if (index <= len - 4) {
|
|
11448
|
+
h64 = conceptU64(h64 ^ (BigInt(conceptReadUInt32LE(data, index) >>> 0) * CONCEPT_PRIME64_1));
|
|
11449
|
+
h64 = conceptU64(conceptRotateLeft(h64, 23) * CONCEPT_PRIME64_2 + CONCEPT_PRIME64_3);
|
|
11450
|
+
index += 4;
|
|
11451
|
+
}
|
|
11452
|
+
while (index < len) {
|
|
11453
|
+
h64 = conceptU64(h64 ^ (BigInt(data[index]) * CONCEPT_PRIME64_5));
|
|
11454
|
+
h64 = conceptU64(conceptRotateLeft(h64, 11) * CONCEPT_PRIME64_1);
|
|
11455
|
+
index += 1;
|
|
11456
|
+
}
|
|
11457
|
+
|
|
11458
|
+
h64 = conceptU64(h64 ^ (h64 >> 33n));
|
|
11459
|
+
h64 = conceptU64(h64 * CONCEPT_PRIME64_2);
|
|
11460
|
+
h64 = conceptU64(h64 ^ (h64 >> 29n));
|
|
11461
|
+
h64 = conceptU64(h64 * CONCEPT_PRIME64_3);
|
|
11462
|
+
h64 = conceptU64(h64 ^ (h64 >> 32n));
|
|
11463
|
+
return h64 & CONCEPT_U64_MASK;
|
|
11464
|
+
}
|
|
11465
|
+
|
|
11466
|
+
function conceptHash64Hex(signature) {
|
|
11467
|
+
const clean = String(signature || '').trim();
|
|
11468
|
+
if (!clean) {
|
|
11469
|
+
const err = new Error('signature is required');
|
|
11470
|
+
err.statusCode = 400;
|
|
11471
|
+
throw err;
|
|
11472
|
+
}
|
|
11473
|
+
return `0x${conceptXxHash64(Buffer.from(clean, 'utf8')).toString(16).padStart(16, '0')}`;
|
|
11474
|
+
}
|
|
11475
|
+
|
|
11476
|
+
function normalizeConceptHex64(value, field = 'id') {
|
|
11477
|
+
const text = String(value || '').trim().toLowerCase();
|
|
11478
|
+
if (!/^0x[0-9a-f]{16}$/.test(text)) {
|
|
11479
|
+
const err = new Error(`${field} must be 0x[0-9a-f]{16}`);
|
|
11480
|
+
err.statusCode = 400;
|
|
11481
|
+
throw err;
|
|
11482
|
+
}
|
|
11483
|
+
return text;
|
|
11484
|
+
}
|
|
11485
|
+
|
|
11486
|
+
function conceptSqlKeyString(hex64) {
|
|
11487
|
+
const unsigned = BigInt(hex64);
|
|
11488
|
+
return unsigned > CONCEPT_I64_MAX
|
|
11489
|
+
? (unsigned - CONCEPT_U64_SIZE).toString()
|
|
11490
|
+
: unsigned.toString();
|
|
11491
|
+
}
|
|
11492
|
+
|
|
11493
|
+
async function loadNodeSqliteModule() {
|
|
11494
|
+
if (!nodeSqliteModulePromise) {
|
|
11495
|
+
nodeSqliteModulePromise = import('node:sqlite').catch(err => {
|
|
11496
|
+
nodeSqliteModulePromise = null;
|
|
11497
|
+
throw err;
|
|
11498
|
+
});
|
|
11499
|
+
}
|
|
11500
|
+
return nodeSqliteModulePromise;
|
|
11501
|
+
}
|
|
11502
|
+
|
|
11503
|
+
function normalizeConceptSequence(ir) {
|
|
11504
|
+
const text = String(ir || '').replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim();
|
|
11505
|
+
if (!text) {
|
|
11506
|
+
const err = new Error('ir is required');
|
|
11507
|
+
err.statusCode = 400;
|
|
11508
|
+
throw err;
|
|
11509
|
+
}
|
|
11510
|
+
if (text.length > 240000) {
|
|
11511
|
+
const err = new Error('ir is too large');
|
|
11512
|
+
err.statusCode = 413;
|
|
11513
|
+
throw err;
|
|
11514
|
+
}
|
|
11515
|
+
|
|
11516
|
+
let parsed;
|
|
11517
|
+
try {
|
|
11518
|
+
parsed = JSON.parse(text);
|
|
11519
|
+
} catch (parseErr) {
|
|
11520
|
+
const err = new Error(`ir must be valid ConceptSequence JSON: ${parseErr?.message || parseErr}`);
|
|
11521
|
+
err.statusCode = 400;
|
|
11522
|
+
throw err;
|
|
11523
|
+
}
|
|
11524
|
+
const literals = Array.isArray(parsed?.literals) ? parsed.literals : [];
|
|
11525
|
+
const instructions = Array.isArray(parsed?.instructions) ? parsed.instructions : [];
|
|
11526
|
+
if (instructions.length === 0) {
|
|
11527
|
+
const err = new Error('ir must include a non-empty instructions array');
|
|
11528
|
+
err.statusCode = 400;
|
|
11529
|
+
throw err;
|
|
11530
|
+
}
|
|
11531
|
+
return { body: text, literals, instructions };
|
|
11532
|
+
}
|
|
11533
|
+
|
|
11534
|
+
function deterministicConceptVector(signature, description, dimensions = 16) {
|
|
11535
|
+
const size = Math.max(4, Math.min(64, Math.trunc(Number(dimensions) || 16)));
|
|
11536
|
+
const input = `${signature}\n\nDescription: ${description || ''}`;
|
|
11537
|
+
return Array.from({ length: size }, (_, index) => {
|
|
11538
|
+
const hash = BigInt(conceptHash64Hex(`${input}#${index}`));
|
|
11539
|
+
const normalized = Number(hash & 0xffffn) / 32767.5 - 1;
|
|
11540
|
+
return Number(normalized.toFixed(6));
|
|
11541
|
+
});
|
|
11542
|
+
}
|
|
11543
|
+
|
|
11544
|
+
function serializeConceptFloatVectorBase64(vector) {
|
|
11545
|
+
const values = Array.isArray(vector) ? vector : [];
|
|
11546
|
+
const buffer = Buffer.alloc(values.length * 4);
|
|
11547
|
+
values.forEach((value, index) => {
|
|
11548
|
+
buffer.writeFloatLE(Number(value) || 0, index * 4);
|
|
11549
|
+
});
|
|
11550
|
+
return buffer.toString('base64');
|
|
11551
|
+
}
|
|
11552
|
+
|
|
11553
|
+
async function readJsonIfExists(filePath, fallback) {
|
|
11554
|
+
try {
|
|
11555
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
11556
|
+
return JSON.parse(content);
|
|
11557
|
+
} catch (err) {
|
|
11558
|
+
if (err?.code === 'ENOENT') {
|
|
11559
|
+
return fallback;
|
|
11560
|
+
}
|
|
11561
|
+
throw err;
|
|
11562
|
+
}
|
|
11563
|
+
}
|
|
11564
|
+
|
|
11565
|
+
function normalizeNullableConceptText(value) {
|
|
11566
|
+
const text = String(value ?? '').trim();
|
|
11567
|
+
return text ? text : null;
|
|
11568
|
+
}
|
|
11569
|
+
|
|
11570
|
+
function conceptEmbeddingBlobFromBase64(base64) {
|
|
11571
|
+
const text = String(base64 || '').trim();
|
|
11572
|
+
if (!text) return null;
|
|
11573
|
+
return Buffer.from(text, 'base64');
|
|
11574
|
+
}
|
|
11575
|
+
|
|
11576
|
+
function conceptSqliteRowFromRecord(record) {
|
|
11577
|
+
const concept = record?.Concept || {};
|
|
11578
|
+
const sqlKey = String(concept.SqlKey || conceptSqlKeyString(normalizeConceptHex64(concept.Id, 'id'))).trim();
|
|
11579
|
+
return {
|
|
11580
|
+
id: BigInt(sqlKey),
|
|
11581
|
+
idText: sqlKey,
|
|
11582
|
+
signature: String(concept.Signature || ''),
|
|
11583
|
+
body: normalizeNullableConceptText(concept.Body),
|
|
11584
|
+
category: normalizeNullableConceptText(concept.Category),
|
|
11585
|
+
conceptType: normalizeNullableConceptText(concept.ConceptType),
|
|
11586
|
+
createdUtc: normalizeNullableConceptText(concept.CreatedUtc),
|
|
11587
|
+
updatedUtc: normalizeNullableConceptText(concept.UpdatedUtc),
|
|
11588
|
+
description: normalizeNullableConceptText(concept.Description),
|
|
11589
|
+
embedding: conceptEmbeddingBlobFromBase64(concept.EmbeddingBase64),
|
|
11590
|
+
embeddingModel: normalizeNullableConceptText(concept.EmbeddingModel),
|
|
11591
|
+
embeddingUpdatedUtc: normalizeNullableConceptText(concept.EmbeddingUpdatedUtc)
|
|
11592
|
+
};
|
|
11593
|
+
}
|
|
11594
|
+
|
|
11595
|
+
function initializeConceptSqliteDatabase(db) {
|
|
11596
|
+
db.exec(`
|
|
11597
|
+
PRAGMA journal_mode=WAL;
|
|
11598
|
+
PRAGMA synchronous=NORMAL;
|
|
11599
|
+
PRAGMA temp_store=MEMORY;
|
|
11600
|
+
CREATE TABLE IF NOT EXISTS tbl_concepts (
|
|
11601
|
+
id INTEGER PRIMARY KEY,
|
|
11602
|
+
signature TEXT NOT NULL,
|
|
11603
|
+
body TEXT NULL,
|
|
11604
|
+
category TEXT NULL,
|
|
11605
|
+
concept_type TEXT NULL,
|
|
11606
|
+
created_utc TEXT NULL,
|
|
11607
|
+
updated_utc TEXT NULL,
|
|
11608
|
+
description TEXT NULL,
|
|
11609
|
+
embedding BLOB NULL,
|
|
11610
|
+
embedding_model TEXT NULL,
|
|
11611
|
+
embedding_updated_utc TEXT NULL
|
|
11612
|
+
);
|
|
11613
|
+
CREATE INDEX IF NOT EXISTS idx_tbl_concepts_category ON tbl_concepts(category);
|
|
11614
|
+
`);
|
|
11615
|
+
}
|
|
11616
|
+
|
|
11617
|
+
function bindConceptSqliteReadBigInts(statement) {
|
|
11618
|
+
if (typeof statement?.setReadBigInts === 'function') {
|
|
11619
|
+
statement.setReadBigInts(true);
|
|
11620
|
+
}
|
|
11621
|
+
return statement;
|
|
11622
|
+
}
|
|
11623
|
+
|
|
11624
|
+
function normalizeConceptSqliteRow(row, sqlitePath) {
|
|
11625
|
+
if (!row) return null;
|
|
11626
|
+
const embedding = row.embedding ? Buffer.from(row.embedding) : null;
|
|
11627
|
+
const idValue = typeof row.id === 'bigint' ? row.id : BigInt(row.id);
|
|
11628
|
+
const hex = `0x${BigInt.asUintN(64, idValue).toString(16).padStart(16, '0')}`;
|
|
11629
|
+
return {
|
|
11630
|
+
success: true,
|
|
11631
|
+
provider: 'LocalBridgeNativeSQLiteConceptStore',
|
|
11632
|
+
adapterState: 'native-sqlite',
|
|
11633
|
+
originalTable: 'tbl_concepts',
|
|
11634
|
+
sqlitePath,
|
|
11635
|
+
id: hex,
|
|
11636
|
+
sqlKey: idValue.toString(),
|
|
11637
|
+
signature: row.signature || '',
|
|
11638
|
+
body: row.body || null,
|
|
11639
|
+
category: row.category || '',
|
|
11640
|
+
conceptType: row.concept_type || null,
|
|
11641
|
+
createdAt: row.created_utc || null,
|
|
11642
|
+
updatedAt: row.updated_utc || null,
|
|
11643
|
+
description: row.description || null,
|
|
11644
|
+
embeddingBase64: embedding ? embedding.toString('base64') : null,
|
|
11645
|
+
embeddingBytes: embedding ? embedding.length : 0,
|
|
11646
|
+
embeddingModel: row.embedding_model || null,
|
|
11647
|
+
embeddingUpdatedAt: row.embedding_updated_utc || null
|
|
11648
|
+
};
|
|
11649
|
+
}
|
|
11650
|
+
|
|
11651
|
+
function buildConceptCompositeResponse(record) {
|
|
11652
|
+
return {
|
|
11653
|
+
success: true,
|
|
11654
|
+
id: record.Concept.Id,
|
|
11655
|
+
sqlKey: record.Concept.SqlKey,
|
|
11656
|
+
signature: record.Concept.Signature,
|
|
11657
|
+
category: record.Concept.Category,
|
|
11658
|
+
conceptType: record.Concept.ConceptType,
|
|
11659
|
+
path: record.Path,
|
|
11660
|
+
indexPath: record.IndexPath,
|
|
11661
|
+
sha256: record.Sha256,
|
|
11662
|
+
hashAlgorithm: record.HashAlgorithm,
|
|
11663
|
+
embeddingModel: record.Concept.EmbeddingModel,
|
|
11664
|
+
embeddingVector: record.Concept.EmbeddingVector,
|
|
11665
|
+
embeddingBase64: record.Concept.EmbeddingBase64,
|
|
11666
|
+
nativeSqlite: record.NativeSqlite || null,
|
|
11667
|
+
updatedAt: record.Concept.UpdatedUtc
|
|
11668
|
+
};
|
|
11669
|
+
}
|
|
11670
|
+
|
|
11671
|
+
async function saveConceptCompositeRecord(request = {}) {
|
|
11672
|
+
const nowUtc = new Date().toISOString();
|
|
11673
|
+
const signature = clampEvidenceText(request.signature || request.Signature, 500);
|
|
11674
|
+
const id = normalizeConceptHex64(request.id || request.Id || conceptHash64Hex(signature), 'id');
|
|
11675
|
+
const derivedId = conceptHash64Hex(signature);
|
|
11676
|
+
if (id !== derivedId) {
|
|
11677
|
+
const err = new Error(`signature does not match id. signature->id=${derivedId}, id=${id}`);
|
|
11678
|
+
err.statusCode = 400;
|
|
11679
|
+
throw err;
|
|
11680
|
+
}
|
|
11681
|
+
|
|
11682
|
+
const sequence = normalizeConceptSequence(request.ir || request.IR || request.body || request.Body);
|
|
11683
|
+
const description = clampEvidenceText(request.description || request.Description, 2400);
|
|
11684
|
+
const category = clampEvidenceText(request.category || request.Category || 'Composite.Dynamic', 160) || 'Composite.Dynamic';
|
|
11685
|
+
const conceptType = clampEvidenceText(request.conceptType || request.ConceptType || 'Axiom', 80) || 'Axiom';
|
|
11686
|
+
const vector = deterministicConceptVector(signature, description, request.embeddingDimensions || request.EmbeddingDimensions || 16);
|
|
11687
|
+
const baseConceptDir = path.resolve(getAiPath(), 'concepts');
|
|
11688
|
+
const rowDir = path.resolve(baseConceptDir, 'rows');
|
|
11689
|
+
const fileName = `${id.slice(2)}-${slugifyEvidence(signature, 64)}.json`;
|
|
11690
|
+
const fullPath = path.resolve(rowDir, fileName);
|
|
11691
|
+
const indexPath = path.resolve(baseConceptDir, 'tbl_concepts.rows.json');
|
|
11692
|
+
|
|
11693
|
+
if (!isPathWithin(baseConceptDir, fullPath) || !isPathWithin(baseConceptDir, indexPath)) {
|
|
11694
|
+
const err = new Error('Concept path must stay under the concept cache.');
|
|
11695
|
+
err.statusCode = 400;
|
|
11696
|
+
throw err;
|
|
11697
|
+
}
|
|
11698
|
+
|
|
11699
|
+
const relativePath = normalizePathForClient(path.relative(workspacePath, fullPath));
|
|
11700
|
+
const relativeIndexPath = normalizePathForClient(path.relative(workspacePath, indexPath));
|
|
11701
|
+
const conceptRow = {
|
|
11702
|
+
Id: id,
|
|
11703
|
+
SqlKey: conceptSqlKeyString(id),
|
|
11704
|
+
Signature: signature,
|
|
11705
|
+
Body: sequence.body,
|
|
11706
|
+
Category: category,
|
|
11707
|
+
ConceptType: conceptType,
|
|
11708
|
+
CreatedUtc: nowUtc,
|
|
11709
|
+
UpdatedUtc: nowUtc,
|
|
11710
|
+
Description: description || undefined,
|
|
11711
|
+
EmbeddingVector: vector,
|
|
11712
|
+
EmbeddingBase64: serializeConceptFloatVectorBase64(vector),
|
|
11713
|
+
EmbeddingModel: CONCEPT_EMBEDDING_MODEL,
|
|
11714
|
+
EmbeddingUpdatedUtc: nowUtc,
|
|
11715
|
+
AtomCount: sequence.instructions.length,
|
|
11716
|
+
LiteralCount: sequence.literals.length
|
|
11717
|
+
};
|
|
11718
|
+
const record = {
|
|
11719
|
+
Schema: 'MindExecution.Kernel.Store.ConceptConcept/v1',
|
|
11720
|
+
Store: {
|
|
11721
|
+
Provider: 'LocalBridgeJsonConceptStore',
|
|
11722
|
+
OriginalTable: 'tbl_concepts',
|
|
11723
|
+
Notes: 'JSON row projection for local React parity; LocalBridge also mirrors the row into native SQLite tbl_concepts.'
|
|
11724
|
+
},
|
|
11725
|
+
HashAlgorithm: CONCEPT_HASH_ALGORITHM,
|
|
11726
|
+
Concept: conceptRow,
|
|
11727
|
+
Path: relativePath,
|
|
11728
|
+
IndexPath: relativeIndexPath
|
|
11729
|
+
};
|
|
11730
|
+
|
|
11731
|
+
const unsignedJson = JSON.stringify(record, null, 2);
|
|
11732
|
+
record.Sha256 = crypto.createHash('sha256').update(unsignedJson, 'utf8').digest('hex');
|
|
11733
|
+
await writeFileAtomically(fullPath, `${JSON.stringify(record, null, 2)}\n`, 'utf8');
|
|
11734
|
+
|
|
11735
|
+
const currentIndex = await readJsonIfExists(indexPath, {
|
|
11736
|
+
Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
|
|
11737
|
+
Store: 'LocalBridgeJsonConceptStore',
|
|
11738
|
+
HashAlgorithm: CONCEPT_HASH_ALGORITHM,
|
|
11739
|
+
Rows: []
|
|
11740
|
+
});
|
|
11741
|
+
const rows = Array.isArray(currentIndex.Rows) ? currentIndex.Rows : [];
|
|
11742
|
+
const nextRows = [
|
|
11743
|
+
{
|
|
11744
|
+
Id: conceptRow.Id,
|
|
11745
|
+
SqlKey: conceptRow.SqlKey,
|
|
11746
|
+
Signature: conceptRow.Signature,
|
|
11747
|
+
Category: conceptRow.Category,
|
|
11748
|
+
ConceptType: conceptRow.ConceptType,
|
|
11749
|
+
UpdatedUtc: conceptRow.UpdatedUtc,
|
|
11750
|
+
AtomCount: conceptRow.AtomCount,
|
|
11751
|
+
LiteralCount: conceptRow.LiteralCount,
|
|
11752
|
+
Path: relativePath,
|
|
11753
|
+
Sha256: record.Sha256
|
|
11754
|
+
},
|
|
11755
|
+
...rows.filter(row => String(row?.Id || '').toLowerCase() !== conceptRow.Id)
|
|
11756
|
+
].slice(0, 512);
|
|
11757
|
+
|
|
11758
|
+
const nextIndex = {
|
|
11759
|
+
Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
|
|
11760
|
+
Store: 'LocalBridgeJsonConceptStore',
|
|
11761
|
+
HashAlgorithm: CONCEPT_HASH_ALGORITHM,
|
|
11762
|
+
UpdatedUtc: nowUtc,
|
|
11763
|
+
RowCount: nextRows.length,
|
|
11764
|
+
Rows: nextRows
|
|
11765
|
+
};
|
|
11766
|
+
await writeFileAtomically(indexPath, `${JSON.stringify(nextIndex, null, 2)}\n`, 'utf8');
|
|
11767
|
+
record.NativeSqlite = await upsertConceptNativeSqlite(record);
|
|
11768
|
+
return record;
|
|
11769
|
+
}
|
|
11770
|
+
|
|
11771
|
+
function getConceptStorePaths() {
|
|
11772
|
+
const baseConceptDir = path.resolve(getAiPath(), 'concepts');
|
|
11773
|
+
const rowDir = path.resolve(baseConceptDir, 'rows');
|
|
11774
|
+
const indexPath = path.resolve(baseConceptDir, 'tbl_concepts.rows.json');
|
|
11775
|
+
const sqlitePath = path.resolve(baseConceptDir, 'mind_concepts.db');
|
|
11776
|
+
return { baseConceptDir, rowDir, indexPath, sqlitePath };
|
|
11777
|
+
}
|
|
11778
|
+
|
|
11779
|
+
async function upsertConceptNativeSqlite(record) {
|
|
11780
|
+
const { DatabaseSync } = await loadNodeSqliteModule();
|
|
11781
|
+
const { baseConceptDir, sqlitePath } = getConceptStorePaths();
|
|
11782
|
+
if (!isPathWithin(baseConceptDir, sqlitePath)) {
|
|
11783
|
+
const err = new Error('Concept SQLite path must stay under the concept cache.');
|
|
11784
|
+
err.statusCode = 400;
|
|
11785
|
+
throw err;
|
|
11786
|
+
}
|
|
11787
|
+
|
|
11788
|
+
await fs.mkdir(baseConceptDir, { recursive: true });
|
|
11789
|
+
const sqliteRow = conceptSqliteRowFromRecord(record);
|
|
11790
|
+
const db = new DatabaseSync(sqlitePath, { readOnly: false });
|
|
11791
|
+
try {
|
|
11792
|
+
initializeConceptSqliteDatabase(db);
|
|
11793
|
+
db.exec('BEGIN IMMEDIATE;');
|
|
11794
|
+
try {
|
|
11795
|
+
db.prepare(`
|
|
11796
|
+
INSERT INTO tbl_concepts (id, signature, body, category, concept_type, created_utc, updated_utc, description, embedding, embedding_model, embedding_updated_utc)
|
|
11797
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
11798
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
11799
|
+
signature=excluded.signature,
|
|
11800
|
+
body=excluded.body,
|
|
11801
|
+
category=excluded.category,
|
|
11802
|
+
concept_type=excluded.concept_type,
|
|
11803
|
+
created_utc=excluded.created_utc,
|
|
11804
|
+
updated_utc=excluded.updated_utc,
|
|
11805
|
+
description=excluded.description,
|
|
11806
|
+
embedding=excluded.embedding,
|
|
11807
|
+
embedding_model=excluded.embedding_model,
|
|
11808
|
+
embedding_updated_utc=excluded.embedding_updated_utc;
|
|
11809
|
+
`).run(
|
|
11810
|
+
sqliteRow.id,
|
|
11811
|
+
sqliteRow.signature,
|
|
11812
|
+
sqliteRow.body,
|
|
11813
|
+
sqliteRow.category,
|
|
11814
|
+
sqliteRow.conceptType,
|
|
11815
|
+
sqliteRow.createdUtc,
|
|
11816
|
+
sqliteRow.updatedUtc,
|
|
11817
|
+
sqliteRow.description,
|
|
11818
|
+
sqliteRow.embedding,
|
|
11819
|
+
sqliteRow.embeddingModel,
|
|
11820
|
+
sqliteRow.embeddingUpdatedUtc
|
|
11821
|
+
);
|
|
11822
|
+
db.exec('COMMIT;');
|
|
11823
|
+
} catch (err) {
|
|
11824
|
+
try { db.exec('ROLLBACK;'); } catch {}
|
|
11825
|
+
throw err;
|
|
11826
|
+
}
|
|
11827
|
+
|
|
11828
|
+
const countRow = db.prepare('SELECT COUNT(*) AS row_count FROM tbl_concepts;').get();
|
|
11829
|
+
const relativeSqlitePath = normalizePathForClient(path.relative(workspacePath, sqlitePath));
|
|
11830
|
+
return {
|
|
11831
|
+
success: true,
|
|
11832
|
+
provider: 'LocalBridgeNativeSQLiteConceptStore',
|
|
11833
|
+
adapterState: 'native-sqlite',
|
|
11834
|
+
originalTable: 'tbl_concepts',
|
|
11835
|
+
sqlitePath: relativeSqlitePath,
|
|
11836
|
+
rowCount: Number(countRow?.row_count || 0),
|
|
11837
|
+
lastSqlKey: sqliteRow.idText,
|
|
11838
|
+
lastId: record?.Concept?.Id || null
|
|
11839
|
+
};
|
|
11840
|
+
} finally {
|
|
11841
|
+
db.close();
|
|
11842
|
+
}
|
|
11843
|
+
}
|
|
11844
|
+
|
|
11845
|
+
async function readConceptNativeSqliteRowById(id) {
|
|
11846
|
+
const normalizedId = normalizeConceptHex64(id, 'id');
|
|
11847
|
+
const { DatabaseSync } = await loadNodeSqliteModule();
|
|
11848
|
+
const { baseConceptDir, sqlitePath } = getConceptStorePaths();
|
|
11849
|
+
if (!isPathWithin(baseConceptDir, sqlitePath)) {
|
|
11850
|
+
const err = new Error('Concept SQLite path must stay under the concept cache.');
|
|
11851
|
+
err.statusCode = 400;
|
|
11852
|
+
throw err;
|
|
11853
|
+
}
|
|
11854
|
+
|
|
11855
|
+
try {
|
|
11856
|
+
await fs.access(sqlitePath);
|
|
11857
|
+
} catch {
|
|
11858
|
+
const err = new Error('Concept native SQLite database has not been created yet.');
|
|
11859
|
+
err.statusCode = 404;
|
|
11860
|
+
throw err;
|
|
11861
|
+
}
|
|
11862
|
+
|
|
11863
|
+
const db = new DatabaseSync(sqlitePath, { readOnly: true });
|
|
11864
|
+
try {
|
|
11865
|
+
const sqlKey = BigInt(conceptSqlKeyString(normalizedId));
|
|
11866
|
+
const statement = bindConceptSqliteReadBigInts(db.prepare(`
|
|
11867
|
+
SELECT id, signature, body, category, concept_type, created_utc, updated_utc, description, embedding, embedding_model, embedding_updated_utc
|
|
11868
|
+
FROM tbl_concepts
|
|
11869
|
+
WHERE id = ?
|
|
11870
|
+
LIMIT 1;
|
|
11871
|
+
`));
|
|
11872
|
+
const row = statement.get(sqlKey);
|
|
11873
|
+
if (!row) {
|
|
11874
|
+
const err = new Error(`Concept SQLite row not found: ${normalizedId}`);
|
|
11875
|
+
err.statusCode = 404;
|
|
11876
|
+
throw err;
|
|
11877
|
+
}
|
|
11878
|
+
const relativeSqlitePath = normalizePathForClient(path.relative(workspacePath, sqlitePath));
|
|
11879
|
+
return normalizeConceptSqliteRow(row, relativeSqlitePath);
|
|
11880
|
+
} finally {
|
|
11881
|
+
db.close();
|
|
11882
|
+
}
|
|
11883
|
+
}
|
|
11884
|
+
|
|
11885
|
+
async function readConceptStoreIndex() {
|
|
11886
|
+
const { baseConceptDir, indexPath } = getConceptStorePaths();
|
|
11887
|
+
if (!isPathWithin(baseConceptDir, indexPath)) {
|
|
11888
|
+
const err = new Error('Concept index path must stay under the concept cache.');
|
|
11889
|
+
err.statusCode = 400;
|
|
11890
|
+
throw err;
|
|
11891
|
+
}
|
|
11892
|
+
|
|
11893
|
+
const fallback = {
|
|
11894
|
+
Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
|
|
11895
|
+
Store: 'LocalBridgeJsonConceptStore',
|
|
11896
|
+
HashAlgorithm: CONCEPT_HASH_ALGORITHM,
|
|
11897
|
+
UpdatedUtc: null,
|
|
11898
|
+
RowCount: 0,
|
|
11899
|
+
Rows: []
|
|
11900
|
+
};
|
|
11901
|
+
const index = await readJsonIfExists(indexPath, fallback);
|
|
11902
|
+
const rows = Array.isArray(index.Rows) ? index.Rows : [];
|
|
11903
|
+
return {
|
|
11904
|
+
...fallback,
|
|
11905
|
+
...index,
|
|
11906
|
+
Rows: rows,
|
|
11907
|
+
RowCount: Number.isFinite(Number(index.RowCount)) ? Number(index.RowCount) : rows.length,
|
|
11908
|
+
Path: normalizePathForClient(path.relative(workspacePath, indexPath))
|
|
11909
|
+
};
|
|
11910
|
+
}
|
|
11911
|
+
|
|
11912
|
+
async function readConceptNativeSqliteStatus() {
|
|
11913
|
+
const { baseConceptDir, sqlitePath } = getConceptStorePaths();
|
|
11914
|
+
const relativeSqlitePath = normalizePathForClient(path.relative(workspacePath, sqlitePath));
|
|
11915
|
+
try {
|
|
11916
|
+
const { DatabaseSync } = await loadNodeSqliteModule();
|
|
11917
|
+
await fs.access(sqlitePath);
|
|
11918
|
+
const db = new DatabaseSync(sqlitePath, { readOnly: true });
|
|
11919
|
+
try {
|
|
11920
|
+
const tableRows = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tbl_concepts' LIMIT 1;").all();
|
|
11921
|
+
const hasTable = tableRows.length > 0;
|
|
11922
|
+
const rowCount = hasTable ? Number(db.prepare('SELECT COUNT(*) AS row_count FROM tbl_concepts;').get()?.row_count || 0) : 0;
|
|
11923
|
+
const columnRows = hasTable ? db.prepare('PRAGMA table_info(tbl_concepts);').all() : [];
|
|
11924
|
+
return {
|
|
11925
|
+
success: true,
|
|
11926
|
+
provider: 'LocalBridgeNativeSQLiteConceptStore',
|
|
11927
|
+
adapterState: hasTable ? 'native-sqlite' : 'native-sqlite-pending',
|
|
11928
|
+
originalTable: 'tbl_concepts',
|
|
11929
|
+
sqlitePath: relativeSqlitePath,
|
|
11930
|
+
rowCount,
|
|
11931
|
+
hasTable,
|
|
11932
|
+
columns: columnRows.map(row => String(row.name || '')).filter(Boolean)
|
|
11933
|
+
};
|
|
11934
|
+
} finally {
|
|
11935
|
+
db.close();
|
|
11936
|
+
}
|
|
11937
|
+
} catch (err) {
|
|
11938
|
+
if (err?.code === 'ENOENT') {
|
|
11939
|
+
return {
|
|
11940
|
+
success: true,
|
|
11941
|
+
provider: 'LocalBridgeNativeSQLiteConceptStore',
|
|
11942
|
+
adapterState: 'native-sqlite-pending',
|
|
11943
|
+
originalTable: 'tbl_concepts',
|
|
11944
|
+
sqlitePath: relativeSqlitePath,
|
|
11945
|
+
rowCount: 0,
|
|
11946
|
+
hasTable: false,
|
|
11947
|
+
columns: []
|
|
11948
|
+
};
|
|
11949
|
+
}
|
|
11950
|
+
return {
|
|
11951
|
+
success: false,
|
|
11952
|
+
provider: 'LocalBridgeNativeSQLiteConceptStore',
|
|
11953
|
+
adapterState: 'native-sqlite-error',
|
|
11954
|
+
originalTable: 'tbl_concepts',
|
|
11955
|
+
sqlitePath: relativeSqlitePath,
|
|
11956
|
+
rowCount: 0,
|
|
11957
|
+
hasTable: false,
|
|
11958
|
+
columns: [],
|
|
11959
|
+
error: err?.message || String(err)
|
|
11960
|
+
};
|
|
11961
|
+
}
|
|
11962
|
+
}
|
|
11963
|
+
|
|
11964
|
+
function buildConceptStoreStatusResponse(index, nativeSqlite = null) {
|
|
11965
|
+
const rows = Array.isArray(index.Rows) ? index.Rows : [];
|
|
11966
|
+
return {
|
|
11967
|
+
success: true,
|
|
11968
|
+
provider: 'LocalBridgeJsonConceptStore',
|
|
11969
|
+
adapterState: 'json-row-projection',
|
|
11970
|
+
originalTable: 'tbl_concepts',
|
|
11971
|
+
schema: index.Schema || 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
|
|
11972
|
+
hashAlgorithm: index.HashAlgorithm || CONCEPT_HASH_ALGORITHM,
|
|
11973
|
+
embeddingModel: CONCEPT_EMBEDDING_MODEL,
|
|
11974
|
+
rowCount: rows.length,
|
|
11975
|
+
indexPath: index.Path,
|
|
11976
|
+
updatedAt: index.UpdatedUtc || null,
|
|
11977
|
+
latestRows: rows.slice(0, 12).map(row => ({
|
|
11978
|
+
id: row.Id,
|
|
11979
|
+
sqlKey: row.SqlKey,
|
|
11980
|
+
signature: row.Signature,
|
|
11981
|
+
category: row.Category,
|
|
11982
|
+
conceptType: row.ConceptType,
|
|
11983
|
+
atomCount: row.AtomCount,
|
|
11984
|
+
literalCount: row.LiteralCount,
|
|
11985
|
+
path: row.Path,
|
|
11986
|
+
sha256: row.Sha256,
|
|
11987
|
+
updatedAt: row.UpdatedUtc
|
|
11988
|
+
})),
|
|
11989
|
+
sqliteReadyColumns: [
|
|
11990
|
+
'Id',
|
|
11991
|
+
'SqlKey',
|
|
11992
|
+
'Signature',
|
|
11993
|
+
'Body',
|
|
11994
|
+
'Category',
|
|
11995
|
+
'ConceptType',
|
|
11996
|
+
'Description',
|
|
11997
|
+
'EmbeddingVector',
|
|
11998
|
+
'EmbeddingBase64',
|
|
11999
|
+
'EmbeddingModel',
|
|
12000
|
+
'AtomCount',
|
|
12001
|
+
'LiteralCount',
|
|
12002
|
+
'CreatedUtc',
|
|
12003
|
+
'UpdatedUtc'
|
|
12004
|
+
],
|
|
12005
|
+
paidEmbeddingAdapterState: 'adapter-gated',
|
|
12006
|
+
nativeSqliteAdapterState: nativeSqlite?.adapterState || 'native-sqlite-pending',
|
|
12007
|
+
nativeSqlite
|
|
12008
|
+
};
|
|
12009
|
+
}
|
|
12010
|
+
|
|
12011
|
+
async function readConceptCompositeRecordById(id) {
|
|
12012
|
+
const normalizedId = normalizeConceptHex64(id, 'id');
|
|
12013
|
+
const index = await readConceptStoreIndex();
|
|
12014
|
+
const row = (Array.isArray(index.Rows) ? index.Rows : []).find(item => String(item?.Id || '').toLowerCase() === normalizedId);
|
|
12015
|
+
if (!row?.Path) {
|
|
12016
|
+
const err = new Error(`Concept row not found: ${normalizedId}`);
|
|
12017
|
+
err.statusCode = 404;
|
|
12018
|
+
throw err;
|
|
12019
|
+
}
|
|
12020
|
+
|
|
12021
|
+
const fullPath = path.resolve(workspacePath, String(row.Path));
|
|
12022
|
+
const { baseConceptDir } = getConceptStorePaths();
|
|
12023
|
+
if (!isPathWithin(baseConceptDir, fullPath)) {
|
|
12024
|
+
const err = new Error('Concept row path must stay under the concept cache.');
|
|
12025
|
+
err.statusCode = 400;
|
|
12026
|
+
throw err;
|
|
12027
|
+
}
|
|
12028
|
+
|
|
12029
|
+
const record = JSON.parse(await fs.readFile(fullPath, 'utf8'));
|
|
12030
|
+
if (String(record?.Concept?.Id || '').toLowerCase() !== normalizedId) {
|
|
12031
|
+
const err = new Error(`Concept row id mismatch: expected ${normalizedId}`);
|
|
12032
|
+
err.statusCode = 409;
|
|
12033
|
+
throw err;
|
|
12034
|
+
}
|
|
12035
|
+
return record;
|
|
12036
|
+
}
|
|
12037
|
+
|
|
12038
|
+
function getConceptEmbeddingProviderConfig() {
|
|
12039
|
+
const baseUrl = String(
|
|
12040
|
+
process.env.MINDEXEC_CONCEPT_EMBED_BASE_URL
|
|
12041
|
+
|| process.env.OPENAI_BASE_URL
|
|
12042
|
+
|| process.env.OPENROUTER_BASE_URL
|
|
12043
|
+
|| 'https://api.openai.com/v1'
|
|
12044
|
+
).trim().replace(/\/+$/, '');
|
|
12045
|
+
const model = String(
|
|
12046
|
+
process.env.MINDEXEC_CONCEPT_EMBED_MODEL
|
|
12047
|
+
|| process.env.OPENAI_EMBEDDING_MODEL
|
|
12048
|
+
|| 'text-embedding-3-small'
|
|
12049
|
+
).trim();
|
|
12050
|
+
const apiKey = String(
|
|
12051
|
+
process.env.MINDEXEC_CONCEPT_EMBED_API_KEY
|
|
12052
|
+
|| process.env.OPENAI_API_KEY
|
|
12053
|
+
|| process.env.OPENROUTER_API_KEY
|
|
12054
|
+
|| ''
|
|
12055
|
+
).trim();
|
|
12056
|
+
const confirm = String(process.env.MINDEXEC_CONCEPT_EMBED_LIVE_CONFIRM || '').trim();
|
|
12057
|
+
return {
|
|
12058
|
+
baseUrl,
|
|
12059
|
+
model,
|
|
12060
|
+
apiKey,
|
|
12061
|
+
hasApiKey: Boolean(apiKey) && !apiKey.includes('__PUT_YOUR_KEY_HERE__'),
|
|
12062
|
+
confirm,
|
|
12063
|
+
confirmed: confirm === CONCEPT_EMBED_LIVE_CONFIRM_VALUE
|
|
12064
|
+
};
|
|
12065
|
+
}
|
|
12066
|
+
|
|
12067
|
+
function buildConceptEmbeddingReadinessResponse() {
|
|
12068
|
+
const config = getConceptEmbeddingProviderConfig();
|
|
12069
|
+
const url = new URL(`${config.baseUrl}/embeddings`);
|
|
12070
|
+
return {
|
|
12071
|
+
success: true,
|
|
12072
|
+
provider: 'OpenAI-compatible embeddings',
|
|
12073
|
+
adapterState: config.confirmed && config.hasApiKey ? 'available-opt-in' : 'adapter-gated',
|
|
12074
|
+
confirmationEnv: 'MINDEXEC_CONCEPT_EMBED_LIVE_CONFIRM',
|
|
12075
|
+
requiredConfirmation: CONCEPT_EMBED_LIVE_CONFIRM_VALUE,
|
|
12076
|
+
confirmationState: config.confirmed ? 'confirmed' : 'missing',
|
|
12077
|
+
apiKeyState: config.hasApiKey ? 'present' : 'missing',
|
|
12078
|
+
baseUrlHost: url.host,
|
|
12079
|
+
endpointPath: url.pathname,
|
|
12080
|
+
model: config.model,
|
|
12081
|
+
inputPolicy: 'signature + "\\n\\nDescription: " + description',
|
|
12082
|
+
storesEmbeddingBase64: true,
|
|
12083
|
+
defaultRunMode: 'blocked-until-confirmed'
|
|
12084
|
+
};
|
|
12085
|
+
}
|
|
12086
|
+
|
|
12087
|
+
function normalizeConceptEmbeddingRequest(request = {}) {
|
|
12088
|
+
const signature = clampEvidenceText(request.signature || request.Signature, 500);
|
|
12089
|
+
const description = clampEvidenceText(request.description || request.Description, 2400);
|
|
12090
|
+
if (!signature.trim()) {
|
|
12091
|
+
const err = new Error('signature is required');
|
|
12092
|
+
err.statusCode = 400;
|
|
12093
|
+
throw err;
|
|
12094
|
+
}
|
|
12095
|
+
if (!description.trim()) {
|
|
12096
|
+
const err = new Error('description is required');
|
|
12097
|
+
err.statusCode = 400;
|
|
12098
|
+
throw err;
|
|
12099
|
+
}
|
|
12100
|
+
return {
|
|
12101
|
+
signature: signature.trim(),
|
|
12102
|
+
description: description.trim(),
|
|
12103
|
+
category: clampEvidenceText(request.category || request.Category || '', 160),
|
|
12104
|
+
conceptType: clampEvidenceText(request.conceptType || request.ConceptType || 'Axiom', 80) || 'Axiom'
|
|
12105
|
+
};
|
|
12106
|
+
}
|
|
12107
|
+
|
|
12108
|
+
async function callConceptEmbeddingProvider(input, config) {
|
|
12109
|
+
const controller = new AbortController();
|
|
12110
|
+
const timeout = setTimeout(() => controller.abort(), 45000);
|
|
12111
|
+
try {
|
|
12112
|
+
const response = await fetch(`${config.baseUrl}/embeddings`, {
|
|
12113
|
+
method: 'POST',
|
|
12114
|
+
headers: {
|
|
12115
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
12116
|
+
'Content-Type': 'application/json'
|
|
12117
|
+
},
|
|
12118
|
+
body: JSON.stringify({ model: config.model, input }),
|
|
12119
|
+
signal: controller.signal
|
|
12120
|
+
});
|
|
12121
|
+
const text = await response.text();
|
|
12122
|
+
if (!response.ok) {
|
|
12123
|
+
const err = new Error(`OpenAI-compatible embeddings error ${response.status}: ${text.slice(0, 500)}`);
|
|
12124
|
+
err.statusCode = 502;
|
|
12125
|
+
throw err;
|
|
12126
|
+
}
|
|
12127
|
+
let payload;
|
|
12128
|
+
try {
|
|
12129
|
+
payload = text ? JSON.parse(text) : {};
|
|
12130
|
+
} catch (parseErr) {
|
|
12131
|
+
const err = new Error(`Embedding provider returned invalid JSON: ${parseErr?.message || parseErr}`);
|
|
12132
|
+
err.statusCode = 502;
|
|
12133
|
+
throw err;
|
|
12134
|
+
}
|
|
12135
|
+
const embedding = payload?.data?.[0]?.embedding;
|
|
12136
|
+
if (!Array.isArray(embedding) || embedding.length === 0) {
|
|
12137
|
+
const err = new Error('Embedding provider returned an empty embedding.');
|
|
12138
|
+
err.statusCode = 502;
|
|
12139
|
+
throw err;
|
|
12140
|
+
}
|
|
12141
|
+
if (embedding.length > 16384) {
|
|
12142
|
+
const err = new Error(`Embedding vector too large: ${embedding.length}`);
|
|
12143
|
+
err.statusCode = 413;
|
|
12144
|
+
throw err;
|
|
12145
|
+
}
|
|
12146
|
+
return embedding.map(value => Number(value) || 0);
|
|
12147
|
+
} finally {
|
|
12148
|
+
clearTimeout(timeout);
|
|
12149
|
+
}
|
|
12150
|
+
}
|
|
12151
|
+
|
|
12152
|
+
async function upsertConceptEmbeddingRecord(request = {}) {
|
|
12153
|
+
const normalized = normalizeConceptEmbeddingRequest(request);
|
|
12154
|
+
const config = getConceptEmbeddingProviderConfig();
|
|
12155
|
+
if (!config.confirmed) {
|
|
12156
|
+
const err = new Error(`Embedding provider calls require MINDEXEC_CONCEPT_EMBED_LIVE_CONFIRM=${CONCEPT_EMBED_LIVE_CONFIRM_VALUE}`);
|
|
12157
|
+
err.statusCode = 403;
|
|
12158
|
+
throw err;
|
|
12159
|
+
}
|
|
12160
|
+
if (!config.hasApiKey) {
|
|
12161
|
+
const err = new Error('Embedding provider API key is missing from server environment.');
|
|
12162
|
+
err.statusCode = 403;
|
|
12163
|
+
throw err;
|
|
12164
|
+
}
|
|
12165
|
+
|
|
12166
|
+
const id = conceptHash64Hex(normalized.signature);
|
|
12167
|
+
let existing = null;
|
|
12168
|
+
try {
|
|
12169
|
+
existing = await readConceptCompositeRecordById(id);
|
|
12170
|
+
} catch (err) {
|
|
12171
|
+
if (Number(err?.statusCode) !== 404) throw err;
|
|
12172
|
+
}
|
|
12173
|
+
|
|
12174
|
+
const input = `${normalized.signature}\n\nDescription: ${normalized.description}`;
|
|
12175
|
+
const vector = await callConceptEmbeddingProvider(input, config);
|
|
12176
|
+
const nowUtc = new Date().toISOString();
|
|
12177
|
+
const { baseConceptDir, rowDir, indexPath } = getConceptStorePaths();
|
|
12178
|
+
const fileName = existing?.Path
|
|
12179
|
+
? path.basename(existing.Path)
|
|
12180
|
+
: `${id.slice(2)}-${slugifyEvidence(normalized.signature, 64)}.json`;
|
|
12181
|
+
const fullPath = existing?.Path
|
|
12182
|
+
? path.resolve(workspacePath, existing.Path)
|
|
12183
|
+
: path.resolve(rowDir, fileName);
|
|
12184
|
+
|
|
12185
|
+
if (!isPathWithin(baseConceptDir, fullPath) || !isPathWithin(baseConceptDir, indexPath)) {
|
|
12186
|
+
const err = new Error('Concept embedding path must stay under the concept cache.');
|
|
12187
|
+
err.statusCode = 400;
|
|
12188
|
+
throw err;
|
|
12189
|
+
}
|
|
12190
|
+
|
|
12191
|
+
const relativePath = normalizePathForClient(path.relative(workspacePath, fullPath));
|
|
12192
|
+
const relativeIndexPath = normalizePathForClient(path.relative(workspacePath, indexPath));
|
|
12193
|
+
const previousConcept = existing?.Concept || {};
|
|
12194
|
+
const conceptRow = {
|
|
12195
|
+
Id: id,
|
|
12196
|
+
SqlKey: conceptSqlKeyString(id),
|
|
12197
|
+
Signature: normalized.signature,
|
|
12198
|
+
Body: previousConcept.Body,
|
|
12199
|
+
Category: normalized.category || previousConcept.Category || '',
|
|
12200
|
+
ConceptType: normalized.conceptType || previousConcept.ConceptType || 'Axiom',
|
|
12201
|
+
CreatedUtc: previousConcept.CreatedUtc || nowUtc,
|
|
12202
|
+
UpdatedUtc: nowUtc,
|
|
12203
|
+
Description: normalized.description,
|
|
12204
|
+
EmbeddingVector: vector,
|
|
12205
|
+
EmbeddingBase64: serializeConceptFloatVectorBase64(vector),
|
|
12206
|
+
EmbeddingModel: config.model,
|
|
12207
|
+
EmbeddingUpdatedUtc: nowUtc,
|
|
12208
|
+
AtomCount: Number(previousConcept.AtomCount || 0),
|
|
12209
|
+
LiteralCount: Number(previousConcept.LiteralCount || 0)
|
|
12210
|
+
};
|
|
12211
|
+
const record = {
|
|
12212
|
+
Schema: 'MindExecution.Kernel.Store.ConceptConcept/v1',
|
|
12213
|
+
Store: {
|
|
12214
|
+
Provider: 'LocalBridgeJsonConceptStore',
|
|
12215
|
+
OriginalTable: 'tbl_concepts',
|
|
12216
|
+
Notes: 'OpenAI-compatible embedding provider result stored as JSON row projection and mirrored into native SQLite tbl_concepts.'
|
|
12217
|
+
},
|
|
12218
|
+
HashAlgorithm: CONCEPT_HASH_ALGORITHM,
|
|
12219
|
+
Concept: conceptRow,
|
|
12220
|
+
Path: relativePath,
|
|
12221
|
+
IndexPath: relativeIndexPath
|
|
12222
|
+
};
|
|
12223
|
+
|
|
12224
|
+
const unsignedJson = JSON.stringify(record, null, 2);
|
|
12225
|
+
record.Sha256 = crypto.createHash('sha256').update(unsignedJson, 'utf8').digest('hex');
|
|
12226
|
+
await writeFileAtomically(fullPath, `${JSON.stringify(record, null, 2)}\n`, 'utf8');
|
|
12227
|
+
|
|
12228
|
+
const currentIndex = await readJsonIfExists(indexPath, {
|
|
12229
|
+
Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
|
|
12230
|
+
Store: 'LocalBridgeJsonConceptStore',
|
|
12231
|
+
HashAlgorithm: CONCEPT_HASH_ALGORITHM,
|
|
12232
|
+
Rows: []
|
|
12233
|
+
});
|
|
12234
|
+
const rows = Array.isArray(currentIndex.Rows) ? currentIndex.Rows : [];
|
|
12235
|
+
const nextRows = [
|
|
12236
|
+
{
|
|
12237
|
+
Id: conceptRow.Id,
|
|
12238
|
+
SqlKey: conceptRow.SqlKey,
|
|
12239
|
+
Signature: conceptRow.Signature,
|
|
12240
|
+
Category: conceptRow.Category,
|
|
12241
|
+
ConceptType: conceptRow.ConceptType,
|
|
12242
|
+
UpdatedUtc: conceptRow.UpdatedUtc,
|
|
12243
|
+
AtomCount: conceptRow.AtomCount,
|
|
12244
|
+
LiteralCount: conceptRow.LiteralCount,
|
|
12245
|
+
Path: relativePath,
|
|
12246
|
+
Sha256: record.Sha256,
|
|
12247
|
+
EmbeddingModel: conceptRow.EmbeddingModel,
|
|
12248
|
+
EmbeddingUpdatedUtc: conceptRow.EmbeddingUpdatedUtc
|
|
12249
|
+
},
|
|
12250
|
+
...rows.filter(row => String(row?.Id || '').toLowerCase() !== conceptRow.Id)
|
|
12251
|
+
].slice(0, 512);
|
|
12252
|
+
const nextIndex = {
|
|
12253
|
+
Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
|
|
12254
|
+
Store: 'LocalBridgeJsonConceptStore',
|
|
12255
|
+
HashAlgorithm: CONCEPT_HASH_ALGORITHM,
|
|
12256
|
+
UpdatedUtc: nowUtc,
|
|
12257
|
+
RowCount: nextRows.length,
|
|
12258
|
+
Rows: nextRows
|
|
12259
|
+
};
|
|
12260
|
+
await writeFileAtomically(indexPath, `${JSON.stringify(nextIndex, null, 2)}\n`, 'utf8');
|
|
12261
|
+
record.NativeSqlite = await upsertConceptNativeSqlite(record);
|
|
12262
|
+
return record;
|
|
12263
|
+
}
|
|
12264
|
+
|
|
12265
|
+
function parseHtmlAttributes(attrs) {
|
|
11090
12266
|
const result = {};
|
|
11091
12267
|
const regex = /([A-Za-z_:][-A-Za-z0-9_:.]*)\s*=\s*["']([^"']*)["']/g;
|
|
11092
12268
|
let match;
|
|
@@ -12644,9 +13820,9 @@ app.post('/api/web/search', async (req, res) => {
|
|
|
12644
13820
|
}
|
|
12645
13821
|
});
|
|
12646
13822
|
|
|
12647
|
-
app.post('/api/web/fetch', async (req, res) => {
|
|
12648
|
-
try {
|
|
12649
|
-
const { url, maxChars = 12000 } = req.body || {};
|
|
13823
|
+
app.post('/api/web/fetch', async (req, res) => {
|
|
13824
|
+
try {
|
|
13825
|
+
const { url, maxChars = 12000 } = req.body || {};
|
|
12650
13826
|
if (!url || !String(url).trim()) {
|
|
12651
13827
|
return res.status(400).json({ error: 'URL is required' });
|
|
12652
13828
|
}
|
|
@@ -12662,12 +13838,119 @@ app.post('/api/web/fetch', async (req, res) => {
|
|
|
12662
13838
|
console.error('[Web/Fetch] Error:', err);
|
|
12663
13839
|
const statusCode = Number(err?.statusCode) || 500;
|
|
12664
13840
|
res.status(statusCode).json({ error: err?.message || 'Web fetch failed' });
|
|
12665
|
-
}
|
|
12666
|
-
});
|
|
12667
|
-
|
|
12668
|
-
app.post('/api/
|
|
12669
|
-
try {
|
|
12670
|
-
const
|
|
13841
|
+
}
|
|
13842
|
+
});
|
|
13843
|
+
|
|
13844
|
+
app.post('/api/evidence/save', async (req, res) => {
|
|
13845
|
+
try {
|
|
13846
|
+
const record = await saveEvidenceRecord(req.body || {});
|
|
13847
|
+
logToolAction(
|
|
13848
|
+
'Evidence.Save',
|
|
13849
|
+
`${formatKeyValue('path', tone(record.Path, 'path'))} ${formatKeyValue('kind', record.Kind)} ${formatKeyValue('source', shortenText(record.SourceUrl || record.SourcePath || '-', 100))}`,
|
|
13850
|
+
'success');
|
|
13851
|
+
res.json(buildEvidenceResponse(record));
|
|
13852
|
+
} catch (err) {
|
|
13853
|
+
console.error('[Evidence/Save] Error:', err);
|
|
13854
|
+
const statusCode = Number(err?.statusCode) || 500;
|
|
13855
|
+
res.status(statusCode).json({ success: false, error: err?.message || 'Evidence save failed' });
|
|
13856
|
+
}
|
|
13857
|
+
});
|
|
13858
|
+
|
|
13859
|
+
app.post('/api/concept/define-composite', async (req, res) => {
|
|
13860
|
+
try {
|
|
13861
|
+
const record = await saveConceptCompositeRecord(req.body || {});
|
|
13862
|
+
logToolAction(
|
|
13863
|
+
'Concept.DefineComposite',
|
|
13864
|
+
`${formatKeyValue('id', record.Concept.Id)} ${formatKeyValue('path', tone(record.Path, 'path'))} ${formatKeyValue('atoms', record.Concept.AtomCount)}`,
|
|
13865
|
+
'success');
|
|
13866
|
+
res.json(buildConceptCompositeResponse(record));
|
|
13867
|
+
} catch (err) {
|
|
13868
|
+
console.error('[Concept/DefineComposite] Error:', err);
|
|
13869
|
+
const statusCode = Number(err?.statusCode) || 500;
|
|
13870
|
+
res.status(statusCode).json({ success: false, error: err?.message || 'Concept composite save failed' });
|
|
13871
|
+
}
|
|
13872
|
+
});
|
|
13873
|
+
|
|
13874
|
+
app.get('/api/concept/status', async (req, res) => {
|
|
13875
|
+
try {
|
|
13876
|
+
const index = await readConceptStoreIndex();
|
|
13877
|
+
const nativeSqlite = await readConceptNativeSqliteStatus();
|
|
13878
|
+
const response = buildConceptStoreStatusResponse(index, nativeSqlite);
|
|
13879
|
+
logToolAction(
|
|
13880
|
+
'Concept.Status',
|
|
13881
|
+
`${formatKeyValue('rows', response.rowCount)} ${formatKeyValue('store', response.adapterState)} ${formatKeyValue('sqlite', response.nativeSqliteAdapterState)} ${formatKeyValue('index', tone(response.indexPath || '-', 'path'))}`,
|
|
13882
|
+
response.adapterState === 'json-row-projection' ? 'bridge' : 'warn');
|
|
13883
|
+
res.json(response);
|
|
13884
|
+
} catch (err) {
|
|
13885
|
+
console.error('[Concept/Status] Error:', err);
|
|
13886
|
+
const statusCode = Number(err?.statusCode) || 500;
|
|
13887
|
+
res.status(statusCode).json({ success: false, error: err?.message || 'Concept status failed' });
|
|
13888
|
+
}
|
|
13889
|
+
});
|
|
13890
|
+
|
|
13891
|
+
app.get('/api/concept/row', async (req, res) => {
|
|
13892
|
+
try {
|
|
13893
|
+
const record = await readConceptCompositeRecordById(req.query?.id || req.query?.Id);
|
|
13894
|
+
logToolAction(
|
|
13895
|
+
'Concept.Row',
|
|
13896
|
+
`${formatKeyValue('id', record.Concept.Id)} ${formatKeyValue('path', tone(record.Path, 'path'))} ${formatKeyValue('atoms', record.Concept.AtomCount)}`,
|
|
13897
|
+
'bridge');
|
|
13898
|
+
res.json(buildConceptCompositeResponse(record));
|
|
13899
|
+
} catch (err) {
|
|
13900
|
+
console.error('[Concept/Row] Error:', err);
|
|
13901
|
+
const statusCode = Number(err?.statusCode) || 500;
|
|
13902
|
+
res.status(statusCode).json({ success: false, error: err?.message || 'Concept row read failed' });
|
|
13903
|
+
}
|
|
13904
|
+
});
|
|
13905
|
+
|
|
13906
|
+
app.get('/api/concept/sqlite/row', async (req, res) => {
|
|
13907
|
+
try {
|
|
13908
|
+
const response = await readConceptNativeSqliteRowById(req.query?.id || req.query?.Id);
|
|
13909
|
+
logToolAction(
|
|
13910
|
+
'Concept.SQLite.Row',
|
|
13911
|
+
`${formatKeyValue('id', response.id)} ${formatKeyValue('path', tone(response.sqlitePath, 'path'))} ${formatKeyValue('bytes', response.embeddingBytes)}`,
|
|
13912
|
+
'bridge');
|
|
13913
|
+
res.json(response);
|
|
13914
|
+
} catch (err) {
|
|
13915
|
+
console.error('[Concept/SQLite/Row] Error:', err);
|
|
13916
|
+
const statusCode = Number(err?.statusCode) || 500;
|
|
13917
|
+
res.status(statusCode).json({ success: false, error: err?.message || 'Concept SQLite row read failed' });
|
|
13918
|
+
}
|
|
13919
|
+
});
|
|
13920
|
+
|
|
13921
|
+
app.get('/api/concept/embed/readiness', async (req, res) => {
|
|
13922
|
+
try {
|
|
13923
|
+
const response = buildConceptEmbeddingReadinessResponse();
|
|
13924
|
+
logToolAction(
|
|
13925
|
+
'Concept.Embed.Readiness',
|
|
13926
|
+
`${formatKeyValue('state', response.adapterState)} ${formatKeyValue('model', response.model)} ${formatKeyValue('endpoint', `${response.baseUrlHost}${response.endpointPath}`)}`,
|
|
13927
|
+
response.adapterState === 'available-opt-in' ? 'bridge' : 'warn');
|
|
13928
|
+
res.json(response);
|
|
13929
|
+
} catch (err) {
|
|
13930
|
+
console.error('[Concept/Embed/Readiness] Error:', err);
|
|
13931
|
+
const statusCode = Number(err?.statusCode) || 500;
|
|
13932
|
+
res.status(statusCode).json({ success: false, error: err?.message || 'Concept embed readiness failed' });
|
|
13933
|
+
}
|
|
13934
|
+
});
|
|
13935
|
+
|
|
13936
|
+
app.post('/api/concept/embed', async (req, res) => {
|
|
13937
|
+
try {
|
|
13938
|
+
const record = await upsertConceptEmbeddingRecord(req.body || {});
|
|
13939
|
+
logToolAction(
|
|
13940
|
+
'Concept.Embed',
|
|
13941
|
+
`${formatKeyValue('id', record.Concept.Id)} ${formatKeyValue('dim', Array.isArray(record.Concept.EmbeddingVector) ? record.Concept.EmbeddingVector.length : 0)} ${formatKeyValue('model', record.Concept.EmbeddingModel)}`,
|
|
13942
|
+
'success');
|
|
13943
|
+
res.json(buildConceptCompositeResponse(record));
|
|
13944
|
+
} catch (err) {
|
|
13945
|
+
console.error('[Concept/Embed] Error:', err);
|
|
13946
|
+
const statusCode = Number(err?.statusCode) || 500;
|
|
13947
|
+
res.status(statusCode).json({ success: false, error: err?.message || 'Concept embed failed' });
|
|
13948
|
+
}
|
|
13949
|
+
});
|
|
13950
|
+
|
|
13951
|
+
app.post('/api/browser/open', async (req, res) => {
|
|
13952
|
+
try {
|
|
13953
|
+
const { url } = req.body || {};
|
|
12671
13954
|
if (!url || !String(url).trim()) {
|
|
12672
13955
|
return res.status(400).json({ error: 'URL is required' });
|
|
12673
13956
|
}
|