@mindexec/cli 0.2.340 → 0.2.342

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.
Files changed (265) hide show
  1. package/codex-runtime.js +255 -31
  2. package/package.json +1 -1
  3. package/remote-hub.js +80 -2
  4. package/scripts/remote-fast-live-rate-smoke.mjs +19 -3
  5. package/scripts/remote-fast-mdm-browser-smoke.mjs +28 -2
  6. package/scripts/remote-hub-smoke.mjs +32 -2
  7. package/server.js +1363 -28
  8. package/wwwroot/_headers +50 -17
  9. package/wwwroot/assets/AdminDashboardPage-B2vz2Px9.css +1 -0
  10. package/wwwroot/assets/AdminDashboardPage-DpUfWSRs.js +1 -0
  11. package/wwwroot/assets/AppSidebar-CBqvLonm.js +1 -0
  12. package/wwwroot/assets/AuthPages-Cd5fYgU0.js +1 -0
  13. package/wwwroot/assets/AuthPages-DFGWKWuB.css +1 -0
  14. package/wwwroot/assets/CodePage-Bncc352E.css +1 -0
  15. package/wwwroot/assets/CodePage-D9-cUf4A.js +87 -0
  16. package/wwwroot/assets/CompanyCorePage-ChBnq1ve.css +1 -0
  17. package/wwwroot/assets/CompanyCorePage-D0byTW77.js +13 -0
  18. package/wwwroot/assets/ExecutionModePage-DtMDlqYc.js +18 -0
  19. package/wwwroot/assets/ExecutionModePage-TLuld9l3.css +1 -0
  20. package/wwwroot/assets/LaunchLeadCapture-CiRI1shz.css +1 -0
  21. package/wwwroot/assets/LaunchLeadCapture-CqeoHfvb.js +1 -0
  22. package/wwwroot/assets/MarketingHome-DPzaYzA_.css +1 -0
  23. package/wwwroot/assets/MarketingHome-DbWyEAya.js +1 -0
  24. package/wwwroot/assets/MindCanvas-CME1KpAo.js +48 -0
  25. package/wwwroot/assets/MindCanvas-DiQlUDJu.css +1 -0
  26. package/wwwroot/assets/PlanMasterPage-CJ36rep-.css +1 -0
  27. package/wwwroot/assets/PlanMasterPage-mhlZZK19.js +4 -0
  28. package/wwwroot/assets/PricingPage-Cg_0i_ZR.css +1 -0
  29. package/wwwroot/assets/PricingPage-zVu8-CrF.js +1 -0
  30. package/wwwroot/assets/ToolPages-DIB187pZ.css +1 -0
  31. package/wwwroot/assets/ToolPages-DTSqKzQd.js +28 -0
  32. package/wwwroot/assets/YouTubeSearchPage-IPPa_BIH.css +1 -0
  33. package/wwwroot/assets/YouTubeSearchPage-xGiaLNqk.js +4 -0
  34. package/wwwroot/assets/app-runtime-xD2Z3NdN.js +1 -0
  35. package/wwwroot/assets/canvas-runtime-D1gfvqKp.js +44 -0
  36. package/wwwroot/assets/code-agent-runtime-B5PPZd1t.js +74 -0
  37. package/wwwroot/assets/executionModeSettings-NJqurj-o.js +1 -0
  38. package/wwwroot/assets/index-CP_xejf2.css +1 -0
  39. package/wwwroot/assets/index-CZS-9WFu.js +2 -0
  40. package/wwwroot/assets/marketingTools-DN_rnHeB.js +4 -0
  41. package/wwwroot/assets/mindCanvasSearchWorker-BzPMsHOB.js +1 -0
  42. package/wwwroot/assets/mindexecution-mindcanvas.png +0 -0
  43. package/wwwroot/assets/mindexecution-prod-home-current.png +0 -0
  44. package/wwwroot/assets/mindexecution-prod-pricing-current.png +0 -0
  45. package/wwwroot/assets/pricingCheckoutShell-O-DnwmbU.js +1 -0
  46. package/wwwroot/assets/runtimeSettingsPersistenceProjection-BoNWmYjU.js +1 -0
  47. package/wwwroot/assets/storage-CGDupGH4.js +1 -0
  48. package/wwwroot/assets/supabaseAuthAdapter-C3z334Qw.js +44 -0
  49. package/wwwroot/assets/toolHandoff-D5e5f7t5.js +4 -0
  50. package/wwwroot/assets/vendor-icons-oiW_NVNO.js +681 -0
  51. package/wwwroot/assets/vendor-msgpack-BE8aAsr3.js +1 -0
  52. package/wwwroot/assets/vendor-react-BXzpOyCS.js +40 -0
  53. package/wwwroot/favicon.svg +7 -0
  54. package/wwwroot/index.html +22 -736
  55. package/wwwroot/manifest.webmanifest +18 -21
  56. package/wwwroot/robots.txt +1 -1
  57. package/wwwroot/service-worker.js +5 -31
  58. package/wwwroot/sitemap.xml +21 -9
  59. package/wwwroot/MindExecution.Web.styles.css +0 -3
  60. package/wwwroot/_content/MindExecution.Plugins.Admin/css/admin-dashboard.css +0 -546
  61. package/wwwroot/_content/MindExecution.Plugins.Directory/MindExecution.Plugins.Directory.u7utcng611.bundle.scp.css +0 -7
  62. package/wwwroot/_content/MindExecution.Plugins.Directory/background.png +0 -0
  63. package/wwwroot/_content/MindExecution.Plugins.Directory/directory-manager.js +0 -202
  64. package/wwwroot/_content/MindExecution.Plugins.Directory/exampleJsInterop.js +0 -6
  65. package/wwwroot/_content/MindExecution.Plugins.YouTube/css/youtube-search.css +0 -251
  66. package/wwwroot/_content/MindExecution.Shared/MindExecution.Shared.wsano1j4wp.bundle.scp.css +0 -4
  67. package/wwwroot/_content/MindExecution.Shared/css/admin-dashboard.css +0 -559
  68. package/wwwroot/_content/MindExecution.Shared/css/app.css +0 -1
  69. package/wwwroot/_content/MindExecution.Shared/css/mind-map-overrides.css +0 -3705
  70. package/wwwroot/_content/MindExecution.Shared/fonts/NotoSansKR-Bold.ttf +0 -0
  71. package/wwwroot/_content/MindExecution.Shared/fonts/NotoSansKR-Regular.ttf +0 -0
  72. package/wwwroot/_content/MindExecution.Shared/js/agent-visualization.js +0 -359
  73. package/wwwroot/_content/MindExecution.Shared/js/background-themes.js +0 -1631
  74. package/wwwroot/_content/MindExecution.Shared/js/code-master.js +0 -8316
  75. package/wwwroot/_content/MindExecution.Shared/js/file-system-helper.js +0 -639
  76. package/wwwroot/_content/MindExecution.Shared/js/helpers/InfiniteGridHelper.js +0 -109
  77. package/wwwroot/_content/MindExecution.Shared/js/marked.min.js +0 -69
  78. package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +0 -12909
  79. package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js.backup +0 -1059
  80. package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +0 -24635
  81. package/wwwroot/_content/MindExecution.Shared/js/mind-map-dev-guards.js +0 -325
  82. package/wwwroot/_content/MindExecution.Shared/js/mind-map-dnd.js +0 -1491
  83. package/wwwroot/_content/MindExecution.Shared/js/mind-map-dnd.js.bak +0 -434
  84. package/wwwroot/_content/MindExecution.Shared/js/mind-map-glow-shader.js +0 -260
  85. package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +0 -7829
  86. package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-plan-worker.js +0 -160
  87. package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +0 -10400
  88. package/wwwroot/_content/MindExecution.Shared/js/mind-map-logic-workers.js +0 -977
  89. package/wwwroot/_content/MindExecution.Shared/js/mind-map-menu-manager.js +0 -1531
  90. package/wwwroot/_content/MindExecution.Shared/js/mind-map-multi-select.js +0 -1716
  91. package/wwwroot/_content/MindExecution.Shared/js/mind-map-node-search-worker.js +0 -554
  92. package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +0 -4578
  93. package/wwwroot/_content/MindExecution.Shared/js/mind-map-object-manager.js +0 -489
  94. package/wwwroot/_content/MindExecution.Shared/js/mind-map-object-manager.js.backup +0 -372
  95. package/wwwroot/_content/MindExecution.Shared/js/mind-map-pipeline.js +0 -2203
  96. package/wwwroot/_content/MindExecution.Shared/js/mind-map-text-lod-system.js +0 -646
  97. package/wwwroot/_content/MindExecution.Shared/js/mind-map-text-overlay-v2.js +0 -4735
  98. package/wwwroot/_content/MindExecution.Shared/js/mind-map-texture-factory.js +0 -2383
  99. package/wwwroot/_content/MindExecution.Shared/js/mind-map-texture-factory.js.backup +0 -1258
  100. package/wwwroot/_content/MindExecution.Shared/js/mind-map-visibility-worker.js +0 -890
  101. package/wwwroot/_content/MindExecution.Shared/js/mindmap-toolbar.js +0 -639
  102. package/wwwroot/_content/MindExecution.Shared/js/native-drop-handler.js +0 -170
  103. package/wwwroot/_content/MindExecution.Shared/js/plan-master.js +0 -788
  104. package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +0 -90
  105. package/wwwroot/_content/MindExecution.Shared/js/texture-worker-manager.js +0 -188
  106. package/wwwroot/_content/MindExecution.Shared/js/texture-worker.js +0 -208
  107. package/wwwroot/_content/MindExecution.Shared/js/three.min.js +0 -6
  108. package/wwwroot/_content/MindExecution.Shared/js/titlebar-handler.js +0 -191
  109. package/wwwroot/_content/MindExecution.Shared/js/token-manager.js +0 -37
  110. package/wwwroot/_content/MindExecution.Shared/js/token-worker.js +0 -28
  111. package/wwwroot/_content/MindExecution.Shared/js/troika-bundle.js +0 -5626
  112. package/wwwroot/_content/MindExecution.Shared/js/troika-bundle.js.map +0 -7
  113. package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/css/all.min.css +0 -9
  114. package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-brands-400.ttf +0 -0
  115. package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-brands-400.woff2 +0 -0
  116. package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-regular-400.ttf +0 -0
  117. package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-regular-400.woff2 +0 -0
  118. package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-solid-900.ttf +0 -0
  119. package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/webfonts/fa-solid-900.woff2 +0 -0
  120. package/wwwroot/_content/MindExecution.Shared/models/all-MiniLM-L6-v2-quantized.onnx +0 -0
  121. package/wwwroot/_content/MindExecution.Shared/models/vocab.txt +0 -30522
  122. package/wwwroot/_framework/Google.Protobuf.9h59ukbel7.dll +0 -0
  123. package/wwwroot/_framework/Markdig.d1j7v41cl1.dll +0 -0
  124. package/wwwroot/_framework/MessagePack.Annotations.l6qv48kgpt.dll +0 -0
  125. package/wwwroot/_framework/MessagePack.eqoptzx9d5.dll +0 -0
  126. package/wwwroot/_framework/Microsoft.AspNetCore.Authorization.k7dsih5y5g.dll +0 -0
  127. package/wwwroot/_framework/Microsoft.AspNetCore.Components.6nyje9sa0g.dll +0 -0
  128. package/wwwroot/_framework/Microsoft.AspNetCore.Components.Authorization.iycd6unprw.dll +0 -0
  129. package/wwwroot/_framework/Microsoft.AspNetCore.Components.Web.487u3twia4.dll +0 -0
  130. package/wwwroot/_framework/Microsoft.AspNetCore.Components.WebAssembly.d0gcnmlxxz.dll +0 -0
  131. package/wwwroot/_framework/Microsoft.AspNetCore.Metadata.h4yevl9adi.dll +0 -0
  132. package/wwwroot/_framework/Microsoft.CSharp.8bsm8vx6su.dll +0 -0
  133. package/wwwroot/_framework/Microsoft.Data.Sqlite.jdlxgv2jtg.dll +0 -0
  134. package/wwwroot/_framework/Microsoft.EntityFrameworkCore.4gjazp7kjf.dll +0 -0
  135. package/wwwroot/_framework/Microsoft.EntityFrameworkCore.Abstractions.gocudnvz7b.dll +0 -0
  136. package/wwwroot/_framework/Microsoft.EntityFrameworkCore.Relational.lt4rsvinuo.dll +0 -0
  137. package/wwwroot/_framework/Microsoft.EntityFrameworkCore.Sqlite.69luj0fa9r.dll +0 -0
  138. package/wwwroot/_framework/Microsoft.Extensions.Caching.Abstractions.364t4jh3zz.dll +0 -0
  139. package/wwwroot/_framework/Microsoft.Extensions.Caching.Memory.izlxhpzosu.dll +0 -0
  140. package/wwwroot/_framework/Microsoft.Extensions.Configuration.8zq7hh41o7.dll +0 -0
  141. package/wwwroot/_framework/Microsoft.Extensions.Configuration.Abstractions.8if74zs6ea.dll +0 -0
  142. package/wwwroot/_framework/Microsoft.Extensions.Configuration.Json.duvlngw8i0.dll +0 -0
  143. package/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.Abstractions.t2hh9kvx0o.dll +0 -0
  144. package/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.n4tg99oy8l.dll +0 -0
  145. package/wwwroot/_framework/Microsoft.Extensions.DependencyModel.h0d06ixk3e.dll +0 -0
  146. package/wwwroot/_framework/Microsoft.Extensions.Logging.Abstractions.rl32bkx2sd.dll +0 -0
  147. package/wwwroot/_framework/Microsoft.Extensions.Logging.dlht1xei0t.dll +0 -0
  148. package/wwwroot/_framework/Microsoft.Extensions.Options.qeunebioml.dll +0 -0
  149. package/wwwroot/_framework/Microsoft.Extensions.Primitives.18cr6vnuuz.dll +0 -0
  150. package/wwwroot/_framework/Microsoft.IO.RecyclableMemoryStream.r915vovvw4.dll +0 -0
  151. package/wwwroot/_framework/Microsoft.IdentityModel.Abstractions.1ejljk3erv.dll +0 -0
  152. package/wwwroot/_framework/Microsoft.IdentityModel.JsonWebTokens.1596zr8gne.dll +0 -0
  153. package/wwwroot/_framework/Microsoft.IdentityModel.Logging.229uyvpgio.dll +0 -0
  154. package/wwwroot/_framework/Microsoft.IdentityModel.Tokens.9sibtajc9f.dll +0 -0
  155. package/wwwroot/_framework/Microsoft.JSInterop.WebAssembly.ryia5gxiad.dll +0 -0
  156. package/wwwroot/_framework/Microsoft.JSInterop.ew9vz9o332.dll +0 -0
  157. package/wwwroot/_framework/Microsoft.ML.OnnxRuntime.w9deo1m5ss.dll +0 -0
  158. package/wwwroot/_framework/Microsoft.ML.Tokenizers.cm2vuv2z61.dll +0 -0
  159. package/wwwroot/_framework/Microsoft.NET.StringTools.3qbrf4v2ki.dll +0 -0
  160. package/wwwroot/_framework/MimeMapping.og9ys58ylm.dll +0 -0
  161. package/wwwroot/_framework/MindExecution.Core.y7ffihhajj.dll +0 -0
  162. package/wwwroot/_framework/MindExecution.Kernel.l5y3qroa7p.dll +0 -0
  163. package/wwwroot/_framework/MindExecution.Plugins.Admin.uuf238xa0h.dll +0 -0
  164. package/wwwroot/_framework/MindExecution.Plugins.Business.nyr3v25v48.dll +0 -0
  165. package/wwwroot/_framework/MindExecution.Plugins.Concept.l9z9tx9svt.dll +0 -0
  166. package/wwwroot/_framework/MindExecution.Plugins.Directory.ju87t8h3zs.dll +0 -0
  167. package/wwwroot/_framework/MindExecution.Plugins.PlanMaster.krn3jgvjpa.dll +0 -0
  168. package/wwwroot/_framework/MindExecution.Plugins.YouTube.5m53srfud6.dll +0 -0
  169. package/wwwroot/_framework/MindExecution.Shared.ojp3psugsm.dll +0 -0
  170. package/wwwroot/_framework/MindExecution.Web.82k6ktlkfg.dll +0 -0
  171. package/wwwroot/_framework/Newtonsoft.Json.a56zs13vug.dll +0 -0
  172. package/wwwroot/_framework/SQLitePCLRaw.batteries_v2.rrd1nzawpp.dll +0 -0
  173. package/wwwroot/_framework/SQLitePCLRaw.core.1dxloztpfz.dll +0 -0
  174. package/wwwroot/_framework/SQLitePCLRaw.provider.e_sqlite3.oekyzl53i1.dll +0 -0
  175. package/wwwroot/_framework/Supabase.Core.s1pkj4aj0l.dll +0 -0
  176. package/wwwroot/_framework/Supabase.Functions.qz4nu782sg.dll +0 -0
  177. package/wwwroot/_framework/Supabase.Gotrue.twah27pkik.dll +0 -0
  178. package/wwwroot/_framework/Supabase.Postgrest.gmuuv369ih.dll +0 -0
  179. package/wwwroot/_framework/Supabase.Realtime.ox3kchdy3w.dll +0 -0
  180. package/wwwroot/_framework/Supabase.Storage.fnjnepaowr.dll +0 -0
  181. package/wwwroot/_framework/Supabase.azmaw5pgcz.dll +0 -0
  182. package/wwwroot/_framework/System.Collections.23yxgetbju.dll +0 -0
  183. package/wwwroot/_framework/System.Collections.Concurrent.vow3rm1dku.dll +0 -0
  184. package/wwwroot/_framework/System.Collections.Immutable.ap9596utv5.dll +0 -0
  185. package/wwwroot/_framework/System.Collections.NonGeneric.npjkaz40oc.dll +0 -0
  186. package/wwwroot/_framework/System.Collections.Specialized.ugkjbs6p02.dll +0 -0
  187. package/wwwroot/_framework/System.ComponentModel.Annotations.clwo0z2oyu.dll +0 -0
  188. package/wwwroot/_framework/System.ComponentModel.Primitives.end4v0xe2c.dll +0 -0
  189. package/wwwroot/_framework/System.ComponentModel.TypeConverter.tgtp5sm4iv.dll +0 -0
  190. package/wwwroot/_framework/System.ComponentModel.wupoltkk1t.dll +0 -0
  191. package/wwwroot/_framework/System.Console.9dik0wogo2.dll +0 -0
  192. package/wwwroot/_framework/System.Data.Common.4v8jejsiu0.dll +0 -0
  193. package/wwwroot/_framework/System.Diagnostics.DiagnosticSource.e2q75ondtq.dll +0 -0
  194. package/wwwroot/_framework/System.Diagnostics.Process.9736yjnxs8.dll +0 -0
  195. package/wwwroot/_framework/System.Diagnostics.TraceSource.h9al53gbbw.dll +0 -0
  196. package/wwwroot/_framework/System.Diagnostics.Tracing.h4bcp2fo98.dll +0 -0
  197. package/wwwroot/_framework/System.Drawing.64oovy8qts.dll +0 -0
  198. package/wwwroot/_framework/System.Drawing.Primitives.o6jiqpgbgl.dll +0 -0
  199. package/wwwroot/_framework/System.Formats.Asn1.rylx5ipd40.dll +0 -0
  200. package/wwwroot/_framework/System.IO.Compression.iceabaupns.dll +0 -0
  201. package/wwwroot/_framework/System.IO.Pipelines.uw8csd3mlz.dll +0 -0
  202. package/wwwroot/_framework/System.IdentityModel.Tokens.Jwt.t67es60z5b.dll +0 -0
  203. package/wwwroot/_framework/System.Linq.Expressions.ty95ava37f.dll +0 -0
  204. package/wwwroot/_framework/System.Linq.Queryable.hs2195jrwy.dll +0 -0
  205. package/wwwroot/_framework/System.Linq.hssodjwmlf.dll +0 -0
  206. package/wwwroot/_framework/System.Memory.1k78n7wdxb.dll +0 -0
  207. package/wwwroot/_framework/System.Net.Http.3br8rfql4c.dll +0 -0
  208. package/wwwroot/_framework/System.Net.Http.Json.860wbh17d8.dll +0 -0
  209. package/wwwroot/_framework/System.Net.NetworkInformation.e3wr00853o.dll +0 -0
  210. package/wwwroot/_framework/System.Net.Ping.r5cw4mf1a4.dll +0 -0
  211. package/wwwroot/_framework/System.Net.Primitives.ksxwiwlvhu.dll +0 -0
  212. package/wwwroot/_framework/System.Net.WebSockets.6rt3n3gl2q.dll +0 -0
  213. package/wwwroot/_framework/System.Net.WebSockets.Client.z3usrzo7rz.dll +0 -0
  214. package/wwwroot/_framework/System.Numerics.Tensors.0c7z4mt3on.dll +0 -0
  215. package/wwwroot/_framework/System.Numerics.Vectors.lbdzx8reja.dll +0 -0
  216. package/wwwroot/_framework/System.ObjectModel.yct1gdirzf.dll +0 -0
  217. package/wwwroot/_framework/System.Private.CoreLib.c1dbswx1b2.dll +0 -0
  218. package/wwwroot/_framework/System.Private.Uri.zp9kmg0z93.dll +0 -0
  219. package/wwwroot/_framework/System.Private.Xml.Linq.lgv2n0akl4.dll +0 -0
  220. package/wwwroot/_framework/System.Private.Xml.dpsk8g304y.dll +0 -0
  221. package/wwwroot/_framework/System.Reactive.t3fuon548l.dll +0 -0
  222. package/wwwroot/_framework/System.Reflection.Emit.ILGeneration.1tcuz2cmbk.dll +0 -0
  223. package/wwwroot/_framework/System.Reflection.Emit.Lightweight.ddt2wylovg.dll +0 -0
  224. package/wwwroot/_framework/System.Reflection.Emit.d8vkadiwhg.dll +0 -0
  225. package/wwwroot/_framework/System.Reflection.Primitives.cpsl71xd1z.dll +0 -0
  226. package/wwwroot/_framework/System.Runtime.InteropServices.31vjgsfk1o.dll +0 -0
  227. package/wwwroot/_framework/System.Runtime.InteropServices.JavaScript.pn2wvizzet.dll +0 -0
  228. package/wwwroot/_framework/System.Runtime.InteropServices.RuntimeInformation.l5rk496q70.dll +0 -0
  229. package/wwwroot/_framework/System.Runtime.Intrinsics.0zee9qcqfy.dll +0 -0
  230. package/wwwroot/_framework/System.Runtime.Loader.xw2jr9wl92.dll +0 -0
  231. package/wwwroot/_framework/System.Runtime.Numerics.ezj1dfyvbj.dll +0 -0
  232. package/wwwroot/_framework/System.Runtime.Serialization.Formatters.0y019e9zkr.dll +0 -0
  233. package/wwwroot/_framework/System.Runtime.Serialization.Primitives.bia5wb62c8.dll +0 -0
  234. package/wwwroot/_framework/System.Runtime.h9cduidfkh.dll +0 -0
  235. package/wwwroot/_framework/System.Security.Claims.2r18wim2rl.dll +0 -0
  236. package/wwwroot/_framework/System.Security.Cryptography.qqgybpoucx.dll +0 -0
  237. package/wwwroot/_framework/System.Text.Encoding.Extensions.9t3hs6kyll.dll +0 -0
  238. package/wwwroot/_framework/System.Text.Encodings.Web.wftjfh2crk.dll +0 -0
  239. package/wwwroot/_framework/System.Text.Json.0v0qgmri0w.dll +0 -0
  240. package/wwwroot/_framework/System.Text.RegularExpressions.cvkox11l6l.dll +0 -0
  241. package/wwwroot/_framework/System.Threading.Channels.419493szqu.dll +0 -0
  242. package/wwwroot/_framework/System.Threading.Thread.xhmys87xh5.dll +0 -0
  243. package/wwwroot/_framework/System.Threading.b66vzsz9g1.dll +0 -0
  244. package/wwwroot/_framework/System.Transactions.Local.7zfffdvnwf.dll +0 -0
  245. package/wwwroot/_framework/System.Web.HttpUtility.9up6xfbtuq.dll +0 -0
  246. package/wwwroot/_framework/System.Xml.Linq.n5rzv9nbf7.dll +0 -0
  247. package/wwwroot/_framework/System.Xml.ReaderWriter.ag8pilllob.dll +0 -0
  248. package/wwwroot/_framework/System.Xml.XDocument.sn51jas17n.dll +0 -0
  249. package/wwwroot/_framework/System.brmz7yk5qh.dll +0 -0
  250. package/wwwroot/_framework/Websocket.Client.vapounvmnl.dll +0 -0
  251. package/wwwroot/_framework/blazor.boot.json +0 -305
  252. package/wwwroot/_framework/blazor.webassembly.js +0 -1
  253. package/wwwroot/_framework/dotnet.js +0 -4
  254. package/wwwroot/_framework/dotnet.native.boem75ye5i.wasm +0 -0
  255. package/wwwroot/_framework/dotnet.native.qc8g39g30v.js +0 -16
  256. package/wwwroot/_framework/dotnet.runtime.opaiwunc3t.js +0 -4
  257. package/wwwroot/_framework/icudt_CJK.tjcz0u77k5.dat +0 -0
  258. package/wwwroot/_framework/icudt_EFIGS.tptq2av103.dat +0 -0
  259. package/wwwroot/_framework/icudt_no_CJK.lfu7j35m59.dat +0 -0
  260. package/wwwroot/_framework/netstandard.yvr3prsx0x.dll +0 -0
  261. package/wwwroot/appsettings.json +0 -83
  262. package/wwwroot/icon-192.png +0 -0
  263. package/wwwroot/icon-512.png +0 -0
  264. package/wwwroot/js/marketing-tool.js +0 -180
  265. package/wwwroot/service-worker-assets.js +0 -857
package/server.js CHANGED
@@ -1588,8 +1588,15 @@ const CONTENT_TYPE_BY_EXTENSION = new Map([
1588
1588
  ['.mov', 'video/quicktime'],
1589
1589
  ['.m4v', 'video/mp4'],
1590
1590
  ['.pdf', 'application/pdf'],
1591
- ['.txt', 'text/plain; charset=utf-8'],
1592
- ['.json', 'application/json; charset=utf-8']
1591
+ ['.js', 'text/javascript; charset=utf-8'],
1592
+ ['.mjs', 'text/javascript; charset=utf-8'],
1593
+ ['.css', 'text/css; charset=utf-8'],
1594
+ ['.html', 'text/html; charset=utf-8'],
1595
+ ['.txt', 'text/plain; charset=utf-8'],
1596
+ ['.json', 'application/json; charset=utf-8'],
1597
+ ['.map', 'application/json; charset=utf-8'],
1598
+ ['.webmanifest', 'application/manifest+json; charset=utf-8'],
1599
+ ['.wasm', 'application/wasm']
1593
1600
  ]);
1594
1601
 
1595
1602
  function detectContentTypeFromHeader(header) {
@@ -2000,6 +2007,47 @@ app.get('/api/assets/resolve', async (req, res) => {
2000
2007
  });
2001
2008
  });
2002
2009
 
2010
+ async function trySendPackagedWebAppAsset(req, res, mountPath) {
2011
+ if (!WEB_APP_ROOT || !['GET', 'HEAD'].includes(String(req.method || '').toUpperCase())) {
2012
+ return false;
2013
+ }
2014
+
2015
+ let requestPath = getMountedAssetRequestPath(req, mountPath);
2016
+ try {
2017
+ requestPath = decodeURIComponent(requestPath);
2018
+ } catch {
2019
+ return false;
2020
+ }
2021
+
2022
+ if (!requestPath || requestPath.includes('\0')) {
2023
+ return false;
2024
+ }
2025
+
2026
+ const packagedAssetsRoot = path.resolve(WEB_APP_ROOT, String(mountPath || '').replace(/^\/+/, ''));
2027
+ const packagedAssetPath = path.resolve(packagedAssetsRoot, requestPath);
2028
+ if (!isPathWithin(packagedAssetsRoot, packagedAssetPath)) {
2029
+ return false;
2030
+ }
2031
+
2032
+ let stats = null;
2033
+ try {
2034
+ stats = await fs.stat(packagedAssetPath);
2035
+ } catch {
2036
+ return false;
2037
+ }
2038
+
2039
+ if (!stats.isFile()) {
2040
+ return false;
2041
+ }
2042
+
2043
+ await sendResolvedAssetFile(req, res, packagedAssetPath, {
2044
+ notFoundMessage: 'Web app asset not found',
2045
+ errorScope: 'web',
2046
+ cacheControl: 'public, max-age=31536000, immutable'
2047
+ });
2048
+ return true;
2049
+ }
2050
+
2003
2051
  // Static file serving for assets (direct image loading - bypasses base64 encoding)
2004
2052
  // This allows browsers to directly fetch images via http://127.0.0.1:5147/assets/filename.png
2005
2053
  app.use('/assets', async (req, res, next) => {
@@ -2034,11 +2082,15 @@ app.use('/assets', async (req, res, next) => {
2034
2082
  normalizedRequestPath,
2035
2083
  ['.png', '.jpg', '.jpeg', '.webp', '.gif', '.bmp', '.svg', '.mp4', '.webm', '.mov']
2036
2084
  );
2037
- }
2038
-
2039
- if (!resolvedPath) {
2040
- return res.status(404).json({ error: 'Asset not found' });
2041
- }
2085
+ }
2086
+
2087
+ if (!resolvedPath) {
2088
+ if (await trySendPackagedWebAppAsset(req, res, '/assets')) {
2089
+ return;
2090
+ }
2091
+
2092
+ return res.status(404).json({ error: 'Asset not found' });
2093
+ }
2042
2094
 
2043
2095
  return sendResolvedAssetFile(req, res, resolvedPath, {
2044
2096
  notFoundMessage: 'Asset not found',
@@ -2138,6 +2190,13 @@ const PROTECTED_BRIDGE_ROUTES = [
2138
2190
  { method: 'POST', exact: '/api/dir/delete' },
2139
2191
  { method: 'POST', prefix: '/api/assets/' },
2140
2192
  { method: 'POST', exact: '/api/local-files/register' },
2193
+ { method: 'POST', exact: '/api/evidence/save' },
2194
+ { method: 'POST', exact: '/api/concept/define-composite' },
2195
+ { method: 'GET', exact: '/api/concept/status' },
2196
+ { method: 'GET', exact: '/api/concept/row' },
2197
+ { method: 'GET', exact: '/api/concept/sqlite/row' },
2198
+ { method: 'GET', exact: '/api/concept/embed/readiness' },
2199
+ { method: 'POST', exact: '/api/concept/embed' },
2141
2200
  { method: 'POST', prefix: '/api/browser/act' },
2142
2201
  { method: 'GET', prefix: '/api/company-core/' },
2143
2202
  { method: 'POST', prefix: '/api/company-core/' },
@@ -2661,6 +2720,39 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
2661
2720
  }
2662
2721
 
2663
2722
  const frame = frameEvent.frame || {};
2723
+ const droppedByAgent = Number(frame.droppedByAgent ?? frameEvent.droppedByAgent ?? 0);
2724
+ const dirtyRectSource = frame.dirtyRectCount
2725
+ ?? frame.dirtyRegionCount
2726
+ ?? frameEvent.dirtyRectCount
2727
+ ?? frameEvent.dirtyRegionCount
2728
+ ?? (Array.isArray(frame.dirtyRects) ? frame.dirtyRects.length : undefined)
2729
+ ?? (Array.isArray(frameEvent.dirtyRects) ? frameEvent.dirtyRects.length : undefined)
2730
+ ?? 0;
2731
+ const dirtyRectCount = Number(dirtyRectSource);
2732
+ const dirtyRatioSource = frame.dirtyPixelRatio
2733
+ ?? frame.dirtyRatio
2734
+ ?? frame.dirtyAreaRatio
2735
+ ?? frame.changedPixelRatio
2736
+ ?? frameEvent.dirtyPixelRatio
2737
+ ?? frameEvent.dirtyRatio
2738
+ ?? frameEvent.dirtyAreaRatio
2739
+ ?? frameEvent.changedPixelRatio
2740
+ ?? 0;
2741
+ const dirtyRatioNumber = Number(dirtyRatioSource);
2742
+ const normalizedDirtyPixelRatio = Number.isFinite(dirtyRatioNumber) && dirtyRatioNumber >= 0
2743
+ ? dirtyRatioNumber <= 1
2744
+ ? dirtyRatioNumber
2745
+ : dirtyRatioNumber <= 100
2746
+ ? dirtyRatioNumber / 100
2747
+ : 1
2748
+ : 0;
2749
+ const deltaValue = frame.deltaEncoded ?? frame.isDeltaEncoded ?? frame.deltaFrame
2750
+ ?? frameEvent.deltaEncoded ?? frameEvent.isDeltaEncoded ?? frameEvent.deltaFrame;
2751
+ const deltaEncoded = typeof deltaValue === 'boolean'
2752
+ ? deltaValue
2753
+ : typeof deltaValue === 'number'
2754
+ ? deltaValue > 0
2755
+ : /^(1|true|yes|on|delta)$/i.test(String(deltaValue || '').trim());
2664
2756
  const metadata = {
2665
2757
  type: 'remote.frame.binary',
2666
2758
  kind: frameEvent.kind || 'live',
@@ -2678,7 +2770,16 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
2678
2770
  transport: frame.transport || '',
2679
2771
  contentHash: frame.contentHash || '',
2680
2772
  captureMs: Number(frame.captureMs || 0) || 0,
2681
- sameContentStreak: Number(frame.sameContentStreak || 0) || 0
2773
+ sameContentStreak: Number(frame.sameContentStreak || 0) || 0,
2774
+ droppedByAgent: Number.isFinite(droppedByAgent) && droppedByAgent >= 0
2775
+ ? Math.round(droppedByAgent)
2776
+ : 0,
2777
+ dirtyRectCount: Number.isFinite(dirtyRectCount) && dirtyRectCount >= 0
2778
+ ? Math.round(dirtyRectCount)
2779
+ : 0,
2780
+ dirtyPixelRatio: normalizedDirtyPixelRatio,
2781
+ codec: String(frame.codec || frame.encoder || frame.encoding || frameEvent.codec || frameEvent.encoder || frameEvent.encoding || '').slice(0, 80),
2782
+ deltaEncoded
2682
2783
  };
2683
2784
  const metaBuffer = Buffer.from(JSON.stringify(metadata), 'utf8');
2684
2785
  const header = Buffer.allocUnsafe(4);
@@ -10958,7 +11059,7 @@ function scoreSearchResult(query, item) {
10958
11059
  return score;
10959
11060
  }
10960
11061
 
10961
- function filterSearchResults(query, items, maxResults) {
11062
+ function filterSearchResults(query, items, maxResults) {
10962
11063
  const clampedMax = Math.max(1, Math.min(Number(maxResults) || 5, 8));
10963
11064
  const list = Array.isArray(items) ? items : [];
10964
11065
  if (!requiresSearchRelevanceFilter(query)) {
@@ -10969,10 +11070,29 @@ function filterSearchResults(query, items, maxResults) {
10969
11070
  .map(item => ({ item, score: scoreSearchResult(query, item) }))
10970
11071
  .filter(entry => entry.score > 0)
10971
11072
  .sort((a, b) => b.score - a.score)
10972
- .map(entry => entry.item)
10973
- .slice(0, clampedMax);
10974
- }
10975
- async function searchBing(query, maxResults = 5) {
11073
+ .map(entry => entry.item)
11074
+ .slice(0, clampedMax);
11075
+ }
11076
+
11077
+ function extractDirectSearchUrl(query) {
11078
+ const match = String(query || '').match(/https?:\/\/[^\s"'<>),]+/i);
11079
+ if (!match) {
11080
+ return '';
11081
+ }
11082
+
11083
+ try {
11084
+ const parsed = new URL(match[0]);
11085
+ if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
11086
+ return parsed.toString();
11087
+ }
11088
+ } catch {
11089
+ return '';
11090
+ }
11091
+
11092
+ return '';
11093
+ }
11094
+
11095
+ async function searchBing(query, maxResults = 5) {
10976
11096
  const clampedMax = Math.max(1, Math.min(Number(maxResults) || 5, 8));
10977
11097
  const searchQuery = expandSearchQuery(query);
10978
11098
  const url = `https://www.bing.com/search?q=${encodeURIComponent(searchQuery)}`;
@@ -10998,8 +11118,22 @@ async function searchBing(query, maxResults = 5) {
10998
11118
  };
10999
11119
  }
11000
11120
 
11001
- async function searchWeb(query, maxResults = 5) {
11121
+ async function searchWeb(query, maxResults = 5) {
11002
11122
  const searchQuery = expandSearchQuery(query);
11123
+ const directUrl = extractDirectSearchUrl(searchQuery);
11124
+ if (directUrl) {
11125
+ return {
11126
+ query: searchQuery,
11127
+ source: 'direct-url',
11128
+ retrievedAt: new Date().toISOString(),
11129
+ items: [{
11130
+ title: 'Direct URL evidence',
11131
+ url: directUrl,
11132
+ snippet: `Direct URL extracted from the WebResearch query: ${directUrl}`
11133
+ }]
11134
+ };
11135
+ }
11136
+
11003
11137
  const providers = [
11004
11138
  ['duckduckgo', searchDuckDuckGo],
11005
11139
  ['brave', searchBrave],
@@ -11034,7 +11168,7 @@ async function searchWeb(query, maxResults = 5) {
11034
11168
  throw error;
11035
11169
  }
11036
11170
 
11037
- async function fetchWebPage(url, maxChars = 12000) {
11171
+ async function fetchWebPage(url, maxChars = 12000) {
11038
11172
  let parsedUrl;
11039
11173
  try {
11040
11174
  parsedUrl = new URL(url);
@@ -11083,10 +11217,1104 @@ async function fetchWebPage(url, maxChars = 12000) {
11083
11217
  contentType,
11084
11218
  truncated,
11085
11219
  retrievedAt: new Date().toISOString()
11086
- };
11087
- }
11088
-
11089
- function parseHtmlAttributes(attrs) {
11220
+ };
11221
+ }
11222
+
11223
+ function clampEvidenceText(value, maxLength = 4000) {
11224
+ const text = String(value ?? '').replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim();
11225
+ if (!text) {
11226
+ return '';
11227
+ }
11228
+ return text.length <= maxLength ? text : `${text.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
11229
+ }
11230
+
11231
+ function evidenceArray(value, maxItems = 12, maxItemLength = 500) {
11232
+ const source = Array.isArray(value) ? value : [];
11233
+ const seen = new Set();
11234
+ const items = [];
11235
+ for (const item of source) {
11236
+ const text = clampEvidenceText(item, maxItemLength);
11237
+ const key = text.toLowerCase();
11238
+ if (!text || seen.has(key)) {
11239
+ continue;
11240
+ }
11241
+ seen.add(key);
11242
+ items.push(text);
11243
+ if (items.length >= maxItems) {
11244
+ break;
11245
+ }
11246
+ }
11247
+ return items;
11248
+ }
11249
+
11250
+ function slugifyEvidence(value, maxLength = 56) {
11251
+ const slug = String(value || 'evidence')
11252
+ .normalize('NFKD')
11253
+ .replace(/[\u0300-\u036f]/g, '')
11254
+ .replace(/[^a-zA-Z0-9]+/g, '-')
11255
+ .replace(/^-+|-+$/g, '')
11256
+ .toLowerCase();
11257
+ return (slug || 'evidence').slice(0, maxLength).replace(/-+$/g, '') || 'evidence';
11258
+ }
11259
+
11260
+ function safeEvidenceDirectory(baseDir, relativeDirectory) {
11261
+ const base = path.resolve(baseDir);
11262
+ const raw = String(relativeDirectory || '').trim();
11263
+ if (!raw) {
11264
+ return base;
11265
+ }
11266
+
11267
+ const safeSegments = raw
11268
+ .replaceAll('\\', '/')
11269
+ .split('/')
11270
+ .map(segment => slugifyEvidence(segment, 40))
11271
+ .filter(Boolean)
11272
+ .slice(0, 4);
11273
+ const target = path.resolve(base, ...safeSegments);
11274
+ if (!isPathWithin(base, target)) {
11275
+ const err = new Error('Evidence directory must stay under the evidence cache.');
11276
+ err.statusCode = 400;
11277
+ throw err;
11278
+ }
11279
+ return target;
11280
+ }
11281
+
11282
+ function normalizeEvidenceUrl(value) {
11283
+ const text = clampEvidenceText(value, 1200);
11284
+ if (!text) {
11285
+ return '';
11286
+ }
11287
+
11288
+ try {
11289
+ const parsed = new URL(text);
11290
+ if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
11291
+ return parsed.toString();
11292
+ }
11293
+ } catch {
11294
+ // SourceUrl is optional. Invalid values are ignored instead of persisted.
11295
+ }
11296
+
11297
+ return '';
11298
+ }
11299
+
11300
+ function normalizeStructuredEvidence(value) {
11301
+ const source = value && typeof value === 'object' ? value : {};
11302
+ const sourceUrl = normalizeEvidenceUrl(source.sourceUrl || source.SourceUrl);
11303
+ const sourcePath = clampEvidenceText(source.sourcePath || source.SourcePath, 1200);
11304
+ return {
11305
+ Schema: clampEvidenceText(source.schema || source.Schema || 'facts', 80) || 'facts',
11306
+ SourceType: clampEvidenceText(source.sourceType || source.SourceType || 'web', 80) || 'web',
11307
+ SourceUrl: sourceUrl || undefined,
11308
+ SourcePath: sourcePath || undefined,
11309
+ Title: clampEvidenceText(source.title || source.Title, 240),
11310
+ Summary: clampEvidenceText(source.summary || source.Summary, 2000),
11311
+ Facts: evidenceArray(source.facts || source.Facts, 16, 600),
11312
+ Dates: evidenceArray(source.dates || source.Dates, 12, 120),
11313
+ Links: evidenceArray(source.links || source.Links, 16, 1200),
11314
+ Prices: evidenceArray(source.prices || source.Prices, 12, 120),
11315
+ CharCount: Math.max(0, Math.min(Number(source.charCount || source.CharCount || 0) || 0, 1000000)),
11316
+ ExtractedAtUtc: clampEvidenceText(source.structuredAt || source.extractedAt || source.ExtractedAtUtc, 80) || new Date().toISOString()
11317
+ };
11318
+ }
11319
+
11320
+ function normalizeEvidenceMetadata(value, kind, sourceUrl) {
11321
+ const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
11322
+ const metadata = {};
11323
+ for (const [key, item] of Object.entries(source)) {
11324
+ const safeKey = String(key || '').replace(/[^a-zA-Z0-9_.:-]/g, '').slice(0, 80);
11325
+ const safeValue = clampEvidenceText(item, 500);
11326
+ if (safeKey && safeValue) {
11327
+ metadata[safeKey] = safeValue;
11328
+ }
11329
+ }
11330
+
11331
+ if (!metadata.kind) {
11332
+ metadata.kind = kind;
11333
+ }
11334
+
11335
+ if (sourceUrl) {
11336
+ try {
11337
+ metadata.sourceHost = new URL(sourceUrl).host;
11338
+ } catch {
11339
+ metadata.sourceHost = sourceUrl;
11340
+ }
11341
+ }
11342
+
11343
+ return metadata;
11344
+ }
11345
+
11346
+ function buildEvidenceResponse(record) {
11347
+ return {
11348
+ success: true,
11349
+ id: record.Id,
11350
+ kind: record.Kind,
11351
+ title: record.Title,
11352
+ query: record.Query,
11353
+ sourceUrl: record.SourceUrl,
11354
+ sourcePath: record.SourcePath,
11355
+ excerpt: record.Excerpt,
11356
+ notes: record.Notes,
11357
+ path: record.Path,
11358
+ sha256: record.Sha256,
11359
+ capturedAt: record.CapturedAtUtc,
11360
+ metadata: record.Metadata,
11361
+ structured: record.Structured
11362
+ };
11363
+ }
11364
+
11365
+ async function saveEvidenceRecord(request = {}) {
11366
+ const capturedAt = new Date();
11367
+ const structured = normalizeStructuredEvidence(request.structured || request.Structured);
11368
+ const kind = clampEvidenceText(request.kind || request.Kind || 'evidence', 120) || 'evidence';
11369
+ const sourceUrl = normalizeEvidenceUrl(request.sourceUrl || request.SourceUrl) || structured.SourceUrl || '';
11370
+ const title = clampEvidenceText(request.title || request.Title || structured.Title || request.query || request.Query || sourceUrl || kind, 240);
11371
+ const query = clampEvidenceText(request.query || request.Query, 500);
11372
+ const sourcePath = clampEvidenceText(request.sourcePath || request.SourcePath || structured.SourcePath, 1200);
11373
+ const excerpt = clampEvidenceText(request.excerpt || request.Excerpt || structured.Summary, 2400);
11374
+ const notes = clampEvidenceText(request.notes || request.Notes, 2000);
11375
+ const metadata = normalizeEvidenceMetadata(request.metadata || request.Metadata, kind, sourceUrl);
11376
+ const baseEvidenceDir = path.join(getAiPath(), 'external', 'evidence');
11377
+ const targetDir = safeEvidenceDirectory(baseEvidenceDir, request.relativeDirectory || request.RelativeDirectory);
11378
+ const slugSource = title || query || sourceUrl || sourcePath || kind || 'evidence';
11379
+ const fileName = `${capturedAt.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z')}-${slugifyEvidence(slugSource)}.json`;
11380
+ const fullPath = path.resolve(targetDir, fileName);
11381
+ if (!isPathWithin(baseEvidenceDir, fullPath)) {
11382
+ const err = new Error('Evidence path must stay under the evidence cache.');
11383
+ err.statusCode = 400;
11384
+ throw err;
11385
+ }
11386
+
11387
+ const relativePath = normalizePathForClient(path.relative(workspacePath, fullPath));
11388
+ const id = `evidence-${capturedAt.toISOString().replace(/[-:T.]/g, '').slice(0, 14)}-${crypto.randomUUID().replace(/-/g, '').slice(0, 8)}`;
11389
+ const record = {
11390
+ Id: id,
11391
+ Kind: kind,
11392
+ Title: title,
11393
+ Query: query || undefined,
11394
+ SourceUrl: sourceUrl || undefined,
11395
+ SourcePath: sourcePath || undefined,
11396
+ Excerpt: excerpt,
11397
+ Notes: notes || undefined,
11398
+ CapturedAtUtc: capturedAt.toISOString(),
11399
+ Structured: structured,
11400
+ Metadata: metadata,
11401
+ Path: relativePath
11402
+ };
11403
+
11404
+ const unsignedJson = JSON.stringify(record, null, 2);
11405
+ record.Sha256 = crypto.createHash('sha256').update(unsignedJson, 'utf8').digest('hex');
11406
+ const finalJson = `${JSON.stringify(record, null, 2)}\n`;
11407
+ await writeFileAtomically(fullPath, finalJson, 'utf8');
11408
+ return record;
11409
+ }
11410
+
11411
+ const CONCEPT_HASH_ALGORITHM = 'xxHash64(seed=0, utf8-trim)';
11412
+ const CONCEPT_EMBEDDING_MODEL = 'local-xxhash64-preview-16';
11413
+ const CONCEPT_EMBED_LIVE_CONFIRM_VALUE = 'I_UNDERSTAND_THIS_CALLS_EMBEDDING_PROVIDER';
11414
+ const CONCEPT_U64_MASK = (1n << 64n) - 1n;
11415
+ const CONCEPT_I64_MAX = (1n << 63n) - 1n;
11416
+ const CONCEPT_U64_SIZE = 1n << 64n;
11417
+ const CONCEPT_PRIME64_1 = 11400714785074694791n;
11418
+ const CONCEPT_PRIME64_2 = 14029467366897019727n;
11419
+ const CONCEPT_PRIME64_3 = 1609587929392839161n;
11420
+ const CONCEPT_PRIME64_4 = 9650029242287828579n;
11421
+ const CONCEPT_PRIME64_5 = 2870177450012600261n;
11422
+ let nodeSqliteModulePromise = null;
11423
+
11424
+ function conceptU64(value) {
11425
+ return BigInt.asUintN(64, value);
11426
+ }
11427
+
11428
+ function conceptRotateLeft(value, count) {
11429
+ const shift = BigInt(count);
11430
+ return conceptU64((conceptU64(value) << shift) | (conceptU64(value) >> (64n - shift)));
11431
+ }
11432
+
11433
+ function conceptReadUInt32LE(data, offset) {
11434
+ return Number(data[offset])
11435
+ | (Number(data[offset + 1]) << 8)
11436
+ | (Number(data[offset + 2]) << 16)
11437
+ | (Number(data[offset + 3]) << 24);
11438
+ }
11439
+
11440
+ function conceptReadUInt64LE(data, offset) {
11441
+ let value = 0n;
11442
+ for (let index = 0; index < 8; index += 1) {
11443
+ value |= BigInt(data[offset + index]) << BigInt(index * 8);
11444
+ }
11445
+ return conceptU64(value);
11446
+ }
11447
+
11448
+ function conceptXxHash64Round(acc, input) {
11449
+ let value = conceptU64(acc + conceptU64(input * CONCEPT_PRIME64_2));
11450
+ value = conceptRotateLeft(value, 31);
11451
+ return conceptU64(value * CONCEPT_PRIME64_1);
11452
+ }
11453
+
11454
+ function conceptXxHash64MergeRound(acc, value) {
11455
+ let next = conceptU64(acc ^ conceptXxHash64Round(0n, value));
11456
+ next = conceptU64(next * CONCEPT_PRIME64_1 + CONCEPT_PRIME64_4);
11457
+ return next;
11458
+ }
11459
+
11460
+ function conceptXxHash64(bytes, seed = 0n) {
11461
+ const data = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes || []);
11462
+ const len = data.length;
11463
+ let index = 0;
11464
+ let h64;
11465
+
11466
+ if (len >= 32) {
11467
+ let v1 = conceptU64(seed + CONCEPT_PRIME64_1 + CONCEPT_PRIME64_2);
11468
+ let v2 = conceptU64(seed + CONCEPT_PRIME64_2);
11469
+ let v3 = conceptU64(seed);
11470
+ let v4 = conceptU64(seed - CONCEPT_PRIME64_1);
11471
+ const limit = len - 32;
11472
+ while (index <= limit) {
11473
+ v1 = conceptXxHash64Round(v1, conceptReadUInt64LE(data, index)); index += 8;
11474
+ v2 = conceptXxHash64Round(v2, conceptReadUInt64LE(data, index)); index += 8;
11475
+ v3 = conceptXxHash64Round(v3, conceptReadUInt64LE(data, index)); index += 8;
11476
+ v4 = conceptXxHash64Round(v4, conceptReadUInt64LE(data, index)); index += 8;
11477
+ }
11478
+ h64 = conceptU64(
11479
+ conceptRotateLeft(v1, 1)
11480
+ + conceptRotateLeft(v2, 7)
11481
+ + conceptRotateLeft(v3, 12)
11482
+ + conceptRotateLeft(v4, 18)
11483
+ );
11484
+ h64 = conceptXxHash64MergeRound(h64, v1);
11485
+ h64 = conceptXxHash64MergeRound(h64, v2);
11486
+ h64 = conceptXxHash64MergeRound(h64, v3);
11487
+ h64 = conceptXxHash64MergeRound(h64, v4);
11488
+ } else {
11489
+ h64 = conceptU64(seed + CONCEPT_PRIME64_5);
11490
+ }
11491
+
11492
+ h64 = conceptU64(h64 + BigInt(len));
11493
+ while (index <= len - 8) {
11494
+ const k1 = conceptXxHash64Round(0n, conceptReadUInt64LE(data, index));
11495
+ h64 = conceptU64(h64 ^ k1);
11496
+ h64 = conceptU64(conceptRotateLeft(h64, 27) * CONCEPT_PRIME64_1 + CONCEPT_PRIME64_4);
11497
+ index += 8;
11498
+ }
11499
+ if (index <= len - 4) {
11500
+ h64 = conceptU64(h64 ^ (BigInt(conceptReadUInt32LE(data, index) >>> 0) * CONCEPT_PRIME64_1));
11501
+ h64 = conceptU64(conceptRotateLeft(h64, 23) * CONCEPT_PRIME64_2 + CONCEPT_PRIME64_3);
11502
+ index += 4;
11503
+ }
11504
+ while (index < len) {
11505
+ h64 = conceptU64(h64 ^ (BigInt(data[index]) * CONCEPT_PRIME64_5));
11506
+ h64 = conceptU64(conceptRotateLeft(h64, 11) * CONCEPT_PRIME64_1);
11507
+ index += 1;
11508
+ }
11509
+
11510
+ h64 = conceptU64(h64 ^ (h64 >> 33n));
11511
+ h64 = conceptU64(h64 * CONCEPT_PRIME64_2);
11512
+ h64 = conceptU64(h64 ^ (h64 >> 29n));
11513
+ h64 = conceptU64(h64 * CONCEPT_PRIME64_3);
11514
+ h64 = conceptU64(h64 ^ (h64 >> 32n));
11515
+ return h64 & CONCEPT_U64_MASK;
11516
+ }
11517
+
11518
+ function conceptHash64Hex(signature) {
11519
+ const clean = String(signature || '').trim();
11520
+ if (!clean) {
11521
+ const err = new Error('signature is required');
11522
+ err.statusCode = 400;
11523
+ throw err;
11524
+ }
11525
+ return `0x${conceptXxHash64(Buffer.from(clean, 'utf8')).toString(16).padStart(16, '0')}`;
11526
+ }
11527
+
11528
+ function normalizeConceptHex64(value, field = 'id') {
11529
+ const text = String(value || '').trim().toLowerCase();
11530
+ if (!/^0x[0-9a-f]{16}$/.test(text)) {
11531
+ const err = new Error(`${field} must be 0x[0-9a-f]{16}`);
11532
+ err.statusCode = 400;
11533
+ throw err;
11534
+ }
11535
+ return text;
11536
+ }
11537
+
11538
+ function conceptSqlKeyString(hex64) {
11539
+ const unsigned = BigInt(hex64);
11540
+ return unsigned > CONCEPT_I64_MAX
11541
+ ? (unsigned - CONCEPT_U64_SIZE).toString()
11542
+ : unsigned.toString();
11543
+ }
11544
+
11545
+ async function loadNodeSqliteModule() {
11546
+ if (!nodeSqliteModulePromise) {
11547
+ nodeSqliteModulePromise = import('node:sqlite').catch(err => {
11548
+ nodeSqliteModulePromise = null;
11549
+ throw err;
11550
+ });
11551
+ }
11552
+ return nodeSqliteModulePromise;
11553
+ }
11554
+
11555
+ function normalizeConceptSequence(ir) {
11556
+ const text = String(ir || '').replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim();
11557
+ if (!text) {
11558
+ const err = new Error('ir is required');
11559
+ err.statusCode = 400;
11560
+ throw err;
11561
+ }
11562
+ if (text.length > 240000) {
11563
+ const err = new Error('ir is too large');
11564
+ err.statusCode = 413;
11565
+ throw err;
11566
+ }
11567
+
11568
+ let parsed;
11569
+ try {
11570
+ parsed = JSON.parse(text);
11571
+ } catch (parseErr) {
11572
+ const err = new Error(`ir must be valid ConceptSequence JSON: ${parseErr?.message || parseErr}`);
11573
+ err.statusCode = 400;
11574
+ throw err;
11575
+ }
11576
+ const literals = Array.isArray(parsed?.literals) ? parsed.literals : [];
11577
+ const instructions = Array.isArray(parsed?.instructions) ? parsed.instructions : [];
11578
+ if (instructions.length === 0) {
11579
+ const err = new Error('ir must include a non-empty instructions array');
11580
+ err.statusCode = 400;
11581
+ throw err;
11582
+ }
11583
+ return { body: text, literals, instructions };
11584
+ }
11585
+
11586
+ function deterministicConceptVector(signature, description, dimensions = 16) {
11587
+ const size = Math.max(4, Math.min(64, Math.trunc(Number(dimensions) || 16)));
11588
+ const input = `${signature}\n\nDescription: ${description || ''}`;
11589
+ return Array.from({ length: size }, (_, index) => {
11590
+ const hash = BigInt(conceptHash64Hex(`${input}#${index}`));
11591
+ const normalized = Number(hash & 0xffffn) / 32767.5 - 1;
11592
+ return Number(normalized.toFixed(6));
11593
+ });
11594
+ }
11595
+
11596
+ function serializeConceptFloatVectorBase64(vector) {
11597
+ const values = Array.isArray(vector) ? vector : [];
11598
+ const buffer = Buffer.alloc(values.length * 4);
11599
+ values.forEach((value, index) => {
11600
+ buffer.writeFloatLE(Number(value) || 0, index * 4);
11601
+ });
11602
+ return buffer.toString('base64');
11603
+ }
11604
+
11605
+ async function readJsonIfExists(filePath, fallback) {
11606
+ try {
11607
+ const content = await fs.readFile(filePath, 'utf8');
11608
+ return JSON.parse(content);
11609
+ } catch (err) {
11610
+ if (err?.code === 'ENOENT') {
11611
+ return fallback;
11612
+ }
11613
+ throw err;
11614
+ }
11615
+ }
11616
+
11617
+ function normalizeNullableConceptText(value) {
11618
+ const text = String(value ?? '').trim();
11619
+ return text ? text : null;
11620
+ }
11621
+
11622
+ function conceptEmbeddingBlobFromBase64(base64) {
11623
+ const text = String(base64 || '').trim();
11624
+ if (!text) return null;
11625
+ return Buffer.from(text, 'base64');
11626
+ }
11627
+
11628
+ function conceptSqliteRowFromRecord(record) {
11629
+ const concept = record?.Concept || {};
11630
+ const sqlKey = String(concept.SqlKey || conceptSqlKeyString(normalizeConceptHex64(concept.Id, 'id'))).trim();
11631
+ return {
11632
+ id: BigInt(sqlKey),
11633
+ idText: sqlKey,
11634
+ signature: String(concept.Signature || ''),
11635
+ body: normalizeNullableConceptText(concept.Body),
11636
+ category: normalizeNullableConceptText(concept.Category),
11637
+ conceptType: normalizeNullableConceptText(concept.ConceptType),
11638
+ createdUtc: normalizeNullableConceptText(concept.CreatedUtc),
11639
+ updatedUtc: normalizeNullableConceptText(concept.UpdatedUtc),
11640
+ description: normalizeNullableConceptText(concept.Description),
11641
+ embedding: conceptEmbeddingBlobFromBase64(concept.EmbeddingBase64),
11642
+ embeddingModel: normalizeNullableConceptText(concept.EmbeddingModel),
11643
+ embeddingUpdatedUtc: normalizeNullableConceptText(concept.EmbeddingUpdatedUtc)
11644
+ };
11645
+ }
11646
+
11647
+ function initializeConceptSqliteDatabase(db) {
11648
+ db.exec(`
11649
+ PRAGMA journal_mode=WAL;
11650
+ PRAGMA synchronous=NORMAL;
11651
+ PRAGMA temp_store=MEMORY;
11652
+ CREATE TABLE IF NOT EXISTS tbl_concepts (
11653
+ id INTEGER PRIMARY KEY,
11654
+ signature TEXT NOT NULL,
11655
+ body TEXT NULL,
11656
+ category TEXT NULL,
11657
+ concept_type TEXT NULL,
11658
+ created_utc TEXT NULL,
11659
+ updated_utc TEXT NULL,
11660
+ description TEXT NULL,
11661
+ embedding BLOB NULL,
11662
+ embedding_model TEXT NULL,
11663
+ embedding_updated_utc TEXT NULL
11664
+ );
11665
+ CREATE INDEX IF NOT EXISTS idx_tbl_concepts_category ON tbl_concepts(category);
11666
+ `);
11667
+ }
11668
+
11669
+ function bindConceptSqliteReadBigInts(statement) {
11670
+ if (typeof statement?.setReadBigInts === 'function') {
11671
+ statement.setReadBigInts(true);
11672
+ }
11673
+ return statement;
11674
+ }
11675
+
11676
+ function normalizeConceptSqliteRow(row, sqlitePath) {
11677
+ if (!row) return null;
11678
+ const embedding = row.embedding ? Buffer.from(row.embedding) : null;
11679
+ const idValue = typeof row.id === 'bigint' ? row.id : BigInt(row.id);
11680
+ const hex = `0x${BigInt.asUintN(64, idValue).toString(16).padStart(16, '0')}`;
11681
+ return {
11682
+ success: true,
11683
+ provider: 'LocalBridgeNativeSQLiteConceptStore',
11684
+ adapterState: 'native-sqlite',
11685
+ originalTable: 'tbl_concepts',
11686
+ sqlitePath,
11687
+ id: hex,
11688
+ sqlKey: idValue.toString(),
11689
+ signature: row.signature || '',
11690
+ body: row.body || null,
11691
+ category: row.category || '',
11692
+ conceptType: row.concept_type || null,
11693
+ createdAt: row.created_utc || null,
11694
+ updatedAt: row.updated_utc || null,
11695
+ description: row.description || null,
11696
+ embeddingBase64: embedding ? embedding.toString('base64') : null,
11697
+ embeddingBytes: embedding ? embedding.length : 0,
11698
+ embeddingModel: row.embedding_model || null,
11699
+ embeddingUpdatedAt: row.embedding_updated_utc || null
11700
+ };
11701
+ }
11702
+
11703
+ function buildConceptCompositeResponse(record) {
11704
+ return {
11705
+ success: true,
11706
+ id: record.Concept.Id,
11707
+ sqlKey: record.Concept.SqlKey,
11708
+ signature: record.Concept.Signature,
11709
+ category: record.Concept.Category,
11710
+ conceptType: record.Concept.ConceptType,
11711
+ path: record.Path,
11712
+ indexPath: record.IndexPath,
11713
+ sha256: record.Sha256,
11714
+ hashAlgorithm: record.HashAlgorithm,
11715
+ embeddingModel: record.Concept.EmbeddingModel,
11716
+ embeddingVector: record.Concept.EmbeddingVector,
11717
+ embeddingBase64: record.Concept.EmbeddingBase64,
11718
+ nativeSqlite: record.NativeSqlite || null,
11719
+ updatedAt: record.Concept.UpdatedUtc
11720
+ };
11721
+ }
11722
+
11723
+ async function saveConceptCompositeRecord(request = {}) {
11724
+ const nowUtc = new Date().toISOString();
11725
+ const signature = clampEvidenceText(request.signature || request.Signature, 500);
11726
+ const id = normalizeConceptHex64(request.id || request.Id || conceptHash64Hex(signature), 'id');
11727
+ const derivedId = conceptHash64Hex(signature);
11728
+ if (id !== derivedId) {
11729
+ const err = new Error(`signature does not match id. signature->id=${derivedId}, id=${id}`);
11730
+ err.statusCode = 400;
11731
+ throw err;
11732
+ }
11733
+
11734
+ const sequence = normalizeConceptSequence(request.ir || request.IR || request.body || request.Body);
11735
+ const description = clampEvidenceText(request.description || request.Description, 2400);
11736
+ const category = clampEvidenceText(request.category || request.Category || 'Composite.Dynamic', 160) || 'Composite.Dynamic';
11737
+ const conceptType = clampEvidenceText(request.conceptType || request.ConceptType || 'Axiom', 80) || 'Axiom';
11738
+ const vector = deterministicConceptVector(signature, description, request.embeddingDimensions || request.EmbeddingDimensions || 16);
11739
+ const baseConceptDir = path.resolve(getAiPath(), 'concepts');
11740
+ const rowDir = path.resolve(baseConceptDir, 'rows');
11741
+ const fileName = `${id.slice(2)}-${slugifyEvidence(signature, 64)}.json`;
11742
+ const fullPath = path.resolve(rowDir, fileName);
11743
+ const indexPath = path.resolve(baseConceptDir, 'tbl_concepts.rows.json');
11744
+
11745
+ if (!isPathWithin(baseConceptDir, fullPath) || !isPathWithin(baseConceptDir, indexPath)) {
11746
+ const err = new Error('Concept path must stay under the concept cache.');
11747
+ err.statusCode = 400;
11748
+ throw err;
11749
+ }
11750
+
11751
+ const relativePath = normalizePathForClient(path.relative(workspacePath, fullPath));
11752
+ const relativeIndexPath = normalizePathForClient(path.relative(workspacePath, indexPath));
11753
+ const conceptRow = {
11754
+ Id: id,
11755
+ SqlKey: conceptSqlKeyString(id),
11756
+ Signature: signature,
11757
+ Body: sequence.body,
11758
+ Category: category,
11759
+ ConceptType: conceptType,
11760
+ CreatedUtc: nowUtc,
11761
+ UpdatedUtc: nowUtc,
11762
+ Description: description || undefined,
11763
+ EmbeddingVector: vector,
11764
+ EmbeddingBase64: serializeConceptFloatVectorBase64(vector),
11765
+ EmbeddingModel: CONCEPT_EMBEDDING_MODEL,
11766
+ EmbeddingUpdatedUtc: nowUtc,
11767
+ AtomCount: sequence.instructions.length,
11768
+ LiteralCount: sequence.literals.length
11769
+ };
11770
+ const record = {
11771
+ Schema: 'MindExecution.Kernel.Store.ConceptConcept/v1',
11772
+ Store: {
11773
+ Provider: 'LocalBridgeJsonConceptStore',
11774
+ OriginalTable: 'tbl_concepts',
11775
+ Notes: 'JSON row projection for local React parity; LocalBridge also mirrors the row into native SQLite tbl_concepts.'
11776
+ },
11777
+ HashAlgorithm: CONCEPT_HASH_ALGORITHM,
11778
+ Concept: conceptRow,
11779
+ Path: relativePath,
11780
+ IndexPath: relativeIndexPath
11781
+ };
11782
+
11783
+ const unsignedJson = JSON.stringify(record, null, 2);
11784
+ record.Sha256 = crypto.createHash('sha256').update(unsignedJson, 'utf8').digest('hex');
11785
+ await writeFileAtomically(fullPath, `${JSON.stringify(record, null, 2)}\n`, 'utf8');
11786
+
11787
+ const currentIndex = await readJsonIfExists(indexPath, {
11788
+ Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
11789
+ Store: 'LocalBridgeJsonConceptStore',
11790
+ HashAlgorithm: CONCEPT_HASH_ALGORITHM,
11791
+ Rows: []
11792
+ });
11793
+ const rows = Array.isArray(currentIndex.Rows) ? currentIndex.Rows : [];
11794
+ const nextRows = [
11795
+ {
11796
+ Id: conceptRow.Id,
11797
+ SqlKey: conceptRow.SqlKey,
11798
+ Signature: conceptRow.Signature,
11799
+ Category: conceptRow.Category,
11800
+ ConceptType: conceptRow.ConceptType,
11801
+ UpdatedUtc: conceptRow.UpdatedUtc,
11802
+ AtomCount: conceptRow.AtomCount,
11803
+ LiteralCount: conceptRow.LiteralCount,
11804
+ Path: relativePath,
11805
+ Sha256: record.Sha256
11806
+ },
11807
+ ...rows.filter(row => String(row?.Id || '').toLowerCase() !== conceptRow.Id)
11808
+ ].slice(0, 512);
11809
+
11810
+ const nextIndex = {
11811
+ Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
11812
+ Store: 'LocalBridgeJsonConceptStore',
11813
+ HashAlgorithm: CONCEPT_HASH_ALGORITHM,
11814
+ UpdatedUtc: nowUtc,
11815
+ RowCount: nextRows.length,
11816
+ Rows: nextRows
11817
+ };
11818
+ await writeFileAtomically(indexPath, `${JSON.stringify(nextIndex, null, 2)}\n`, 'utf8');
11819
+ record.NativeSqlite = await upsertConceptNativeSqlite(record);
11820
+ return record;
11821
+ }
11822
+
11823
+ function getConceptStorePaths() {
11824
+ const baseConceptDir = path.resolve(getAiPath(), 'concepts');
11825
+ const rowDir = path.resolve(baseConceptDir, 'rows');
11826
+ const indexPath = path.resolve(baseConceptDir, 'tbl_concepts.rows.json');
11827
+ const sqlitePath = path.resolve(baseConceptDir, 'mind_concepts.db');
11828
+ return { baseConceptDir, rowDir, indexPath, sqlitePath };
11829
+ }
11830
+
11831
+ async function upsertConceptNativeSqlite(record) {
11832
+ const { DatabaseSync } = await loadNodeSqliteModule();
11833
+ const { baseConceptDir, sqlitePath } = getConceptStorePaths();
11834
+ if (!isPathWithin(baseConceptDir, sqlitePath)) {
11835
+ const err = new Error('Concept SQLite path must stay under the concept cache.');
11836
+ err.statusCode = 400;
11837
+ throw err;
11838
+ }
11839
+
11840
+ await fs.mkdir(baseConceptDir, { recursive: true });
11841
+ const sqliteRow = conceptSqliteRowFromRecord(record);
11842
+ const db = new DatabaseSync(sqlitePath, { readOnly: false });
11843
+ try {
11844
+ initializeConceptSqliteDatabase(db);
11845
+ db.exec('BEGIN IMMEDIATE;');
11846
+ try {
11847
+ db.prepare(`
11848
+ INSERT INTO tbl_concepts (id, signature, body, category, concept_type, created_utc, updated_utc, description, embedding, embedding_model, embedding_updated_utc)
11849
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
11850
+ ON CONFLICT(id) DO UPDATE SET
11851
+ signature=excluded.signature,
11852
+ body=excluded.body,
11853
+ category=excluded.category,
11854
+ concept_type=excluded.concept_type,
11855
+ created_utc=excluded.created_utc,
11856
+ updated_utc=excluded.updated_utc,
11857
+ description=excluded.description,
11858
+ embedding=excluded.embedding,
11859
+ embedding_model=excluded.embedding_model,
11860
+ embedding_updated_utc=excluded.embedding_updated_utc;
11861
+ `).run(
11862
+ sqliteRow.id,
11863
+ sqliteRow.signature,
11864
+ sqliteRow.body,
11865
+ sqliteRow.category,
11866
+ sqliteRow.conceptType,
11867
+ sqliteRow.createdUtc,
11868
+ sqliteRow.updatedUtc,
11869
+ sqliteRow.description,
11870
+ sqliteRow.embedding,
11871
+ sqliteRow.embeddingModel,
11872
+ sqliteRow.embeddingUpdatedUtc
11873
+ );
11874
+ db.exec('COMMIT;');
11875
+ } catch (err) {
11876
+ try { db.exec('ROLLBACK;'); } catch {}
11877
+ throw err;
11878
+ }
11879
+
11880
+ const countRow = db.prepare('SELECT COUNT(*) AS row_count FROM tbl_concepts;').get();
11881
+ const relativeSqlitePath = normalizePathForClient(path.relative(workspacePath, sqlitePath));
11882
+ return {
11883
+ success: true,
11884
+ provider: 'LocalBridgeNativeSQLiteConceptStore',
11885
+ adapterState: 'native-sqlite',
11886
+ originalTable: 'tbl_concepts',
11887
+ sqlitePath: relativeSqlitePath,
11888
+ rowCount: Number(countRow?.row_count || 0),
11889
+ lastSqlKey: sqliteRow.idText,
11890
+ lastId: record?.Concept?.Id || null
11891
+ };
11892
+ } finally {
11893
+ db.close();
11894
+ }
11895
+ }
11896
+
11897
+ async function readConceptNativeSqliteRowById(id) {
11898
+ const normalizedId = normalizeConceptHex64(id, 'id');
11899
+ const { DatabaseSync } = await loadNodeSqliteModule();
11900
+ const { baseConceptDir, sqlitePath } = getConceptStorePaths();
11901
+ if (!isPathWithin(baseConceptDir, sqlitePath)) {
11902
+ const err = new Error('Concept SQLite path must stay under the concept cache.');
11903
+ err.statusCode = 400;
11904
+ throw err;
11905
+ }
11906
+
11907
+ try {
11908
+ await fs.access(sqlitePath);
11909
+ } catch {
11910
+ const err = new Error('Concept native SQLite database has not been created yet.');
11911
+ err.statusCode = 404;
11912
+ throw err;
11913
+ }
11914
+
11915
+ const db = new DatabaseSync(sqlitePath, { readOnly: true });
11916
+ try {
11917
+ const sqlKey = BigInt(conceptSqlKeyString(normalizedId));
11918
+ const statement = bindConceptSqliteReadBigInts(db.prepare(`
11919
+ SELECT id, signature, body, category, concept_type, created_utc, updated_utc, description, embedding, embedding_model, embedding_updated_utc
11920
+ FROM tbl_concepts
11921
+ WHERE id = ?
11922
+ LIMIT 1;
11923
+ `));
11924
+ const row = statement.get(sqlKey);
11925
+ if (!row) {
11926
+ const err = new Error(`Concept SQLite row not found: ${normalizedId}`);
11927
+ err.statusCode = 404;
11928
+ throw err;
11929
+ }
11930
+ const relativeSqlitePath = normalizePathForClient(path.relative(workspacePath, sqlitePath));
11931
+ return normalizeConceptSqliteRow(row, relativeSqlitePath);
11932
+ } finally {
11933
+ db.close();
11934
+ }
11935
+ }
11936
+
11937
+ async function readConceptStoreIndex() {
11938
+ const { baseConceptDir, indexPath } = getConceptStorePaths();
11939
+ if (!isPathWithin(baseConceptDir, indexPath)) {
11940
+ const err = new Error('Concept index path must stay under the concept cache.');
11941
+ err.statusCode = 400;
11942
+ throw err;
11943
+ }
11944
+
11945
+ const fallback = {
11946
+ Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
11947
+ Store: 'LocalBridgeJsonConceptStore',
11948
+ HashAlgorithm: CONCEPT_HASH_ALGORITHM,
11949
+ UpdatedUtc: null,
11950
+ RowCount: 0,
11951
+ Rows: []
11952
+ };
11953
+ const index = await readJsonIfExists(indexPath, fallback);
11954
+ const rows = Array.isArray(index.Rows) ? index.Rows : [];
11955
+ return {
11956
+ ...fallback,
11957
+ ...index,
11958
+ Rows: rows,
11959
+ RowCount: Number.isFinite(Number(index.RowCount)) ? Number(index.RowCount) : rows.length,
11960
+ Path: normalizePathForClient(path.relative(workspacePath, indexPath))
11961
+ };
11962
+ }
11963
+
11964
+ async function readConceptNativeSqliteStatus() {
11965
+ const { baseConceptDir, sqlitePath } = getConceptStorePaths();
11966
+ const relativeSqlitePath = normalizePathForClient(path.relative(workspacePath, sqlitePath));
11967
+ try {
11968
+ const { DatabaseSync } = await loadNodeSqliteModule();
11969
+ await fs.access(sqlitePath);
11970
+ const db = new DatabaseSync(sqlitePath, { readOnly: true });
11971
+ try {
11972
+ const tableRows = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tbl_concepts' LIMIT 1;").all();
11973
+ const hasTable = tableRows.length > 0;
11974
+ const rowCount = hasTable ? Number(db.prepare('SELECT COUNT(*) AS row_count FROM tbl_concepts;').get()?.row_count || 0) : 0;
11975
+ const columnRows = hasTable ? db.prepare('PRAGMA table_info(tbl_concepts);').all() : [];
11976
+ return {
11977
+ success: true,
11978
+ provider: 'LocalBridgeNativeSQLiteConceptStore',
11979
+ adapterState: hasTable ? 'native-sqlite' : 'native-sqlite-pending',
11980
+ originalTable: 'tbl_concepts',
11981
+ sqlitePath: relativeSqlitePath,
11982
+ rowCount,
11983
+ hasTable,
11984
+ columns: columnRows.map(row => String(row.name || '')).filter(Boolean)
11985
+ };
11986
+ } finally {
11987
+ db.close();
11988
+ }
11989
+ } catch (err) {
11990
+ if (err?.code === 'ENOENT') {
11991
+ return {
11992
+ success: true,
11993
+ provider: 'LocalBridgeNativeSQLiteConceptStore',
11994
+ adapterState: 'native-sqlite-pending',
11995
+ originalTable: 'tbl_concepts',
11996
+ sqlitePath: relativeSqlitePath,
11997
+ rowCount: 0,
11998
+ hasTable: false,
11999
+ columns: []
12000
+ };
12001
+ }
12002
+ return {
12003
+ success: false,
12004
+ provider: 'LocalBridgeNativeSQLiteConceptStore',
12005
+ adapterState: 'native-sqlite-error',
12006
+ originalTable: 'tbl_concepts',
12007
+ sqlitePath: relativeSqlitePath,
12008
+ rowCount: 0,
12009
+ hasTable: false,
12010
+ columns: [],
12011
+ error: err?.message || String(err)
12012
+ };
12013
+ }
12014
+ }
12015
+
12016
+ function buildConceptStoreStatusResponse(index, nativeSqlite = null) {
12017
+ const rows = Array.isArray(index.Rows) ? index.Rows : [];
12018
+ return {
12019
+ success: true,
12020
+ provider: 'LocalBridgeJsonConceptStore',
12021
+ adapterState: 'json-row-projection',
12022
+ originalTable: 'tbl_concepts',
12023
+ schema: index.Schema || 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
12024
+ hashAlgorithm: index.HashAlgorithm || CONCEPT_HASH_ALGORITHM,
12025
+ embeddingModel: CONCEPT_EMBEDDING_MODEL,
12026
+ rowCount: rows.length,
12027
+ indexPath: index.Path,
12028
+ updatedAt: index.UpdatedUtc || null,
12029
+ latestRows: rows.slice(0, 12).map(row => ({
12030
+ id: row.Id,
12031
+ sqlKey: row.SqlKey,
12032
+ signature: row.Signature,
12033
+ category: row.Category,
12034
+ conceptType: row.ConceptType,
12035
+ atomCount: row.AtomCount,
12036
+ literalCount: row.LiteralCount,
12037
+ path: row.Path,
12038
+ sha256: row.Sha256,
12039
+ updatedAt: row.UpdatedUtc
12040
+ })),
12041
+ sqliteReadyColumns: [
12042
+ 'Id',
12043
+ 'SqlKey',
12044
+ 'Signature',
12045
+ 'Body',
12046
+ 'Category',
12047
+ 'ConceptType',
12048
+ 'Description',
12049
+ 'EmbeddingVector',
12050
+ 'EmbeddingBase64',
12051
+ 'EmbeddingModel',
12052
+ 'AtomCount',
12053
+ 'LiteralCount',
12054
+ 'CreatedUtc',
12055
+ 'UpdatedUtc'
12056
+ ],
12057
+ paidEmbeddingAdapterState: 'adapter-gated',
12058
+ nativeSqliteAdapterState: nativeSqlite?.adapterState || 'native-sqlite-pending',
12059
+ nativeSqlite
12060
+ };
12061
+ }
12062
+
12063
+ async function readConceptCompositeRecordById(id) {
12064
+ const normalizedId = normalizeConceptHex64(id, 'id');
12065
+ const index = await readConceptStoreIndex();
12066
+ const row = (Array.isArray(index.Rows) ? index.Rows : []).find(item => String(item?.Id || '').toLowerCase() === normalizedId);
12067
+ if (!row?.Path) {
12068
+ const err = new Error(`Concept row not found: ${normalizedId}`);
12069
+ err.statusCode = 404;
12070
+ throw err;
12071
+ }
12072
+
12073
+ const fullPath = path.resolve(workspacePath, String(row.Path));
12074
+ const { baseConceptDir } = getConceptStorePaths();
12075
+ if (!isPathWithin(baseConceptDir, fullPath)) {
12076
+ const err = new Error('Concept row path must stay under the concept cache.');
12077
+ err.statusCode = 400;
12078
+ throw err;
12079
+ }
12080
+
12081
+ const record = JSON.parse(await fs.readFile(fullPath, 'utf8'));
12082
+ if (String(record?.Concept?.Id || '').toLowerCase() !== normalizedId) {
12083
+ const err = new Error(`Concept row id mismatch: expected ${normalizedId}`);
12084
+ err.statusCode = 409;
12085
+ throw err;
12086
+ }
12087
+ return record;
12088
+ }
12089
+
12090
+ function getConceptEmbeddingProviderConfig() {
12091
+ const baseUrl = String(
12092
+ process.env.MINDEXEC_CONCEPT_EMBED_BASE_URL
12093
+ || process.env.OPENAI_BASE_URL
12094
+ || process.env.OPENROUTER_BASE_URL
12095
+ || 'https://api.openai.com/v1'
12096
+ ).trim().replace(/\/+$/, '');
12097
+ const model = String(
12098
+ process.env.MINDEXEC_CONCEPT_EMBED_MODEL
12099
+ || process.env.OPENAI_EMBEDDING_MODEL
12100
+ || 'text-embedding-3-small'
12101
+ ).trim();
12102
+ const apiKey = String(
12103
+ process.env.MINDEXEC_CONCEPT_EMBED_API_KEY
12104
+ || process.env.OPENAI_API_KEY
12105
+ || process.env.OPENROUTER_API_KEY
12106
+ || ''
12107
+ ).trim();
12108
+ const confirm = String(process.env.MINDEXEC_CONCEPT_EMBED_LIVE_CONFIRM || '').trim();
12109
+ return {
12110
+ baseUrl,
12111
+ model,
12112
+ apiKey,
12113
+ hasApiKey: Boolean(apiKey) && !apiKey.includes('__PUT_YOUR_KEY_HERE__'),
12114
+ confirm,
12115
+ confirmed: confirm === CONCEPT_EMBED_LIVE_CONFIRM_VALUE
12116
+ };
12117
+ }
12118
+
12119
+ function buildConceptEmbeddingReadinessResponse() {
12120
+ const config = getConceptEmbeddingProviderConfig();
12121
+ const url = new URL(`${config.baseUrl}/embeddings`);
12122
+ return {
12123
+ success: true,
12124
+ provider: 'OpenAI-compatible embeddings',
12125
+ adapterState: config.confirmed && config.hasApiKey ? 'available-opt-in' : 'adapter-gated',
12126
+ confirmationEnv: 'MINDEXEC_CONCEPT_EMBED_LIVE_CONFIRM',
12127
+ requiredConfirmation: CONCEPT_EMBED_LIVE_CONFIRM_VALUE,
12128
+ confirmationState: config.confirmed ? 'confirmed' : 'missing',
12129
+ apiKeyState: config.hasApiKey ? 'present' : 'missing',
12130
+ baseUrlHost: url.host,
12131
+ endpointPath: url.pathname,
12132
+ model: config.model,
12133
+ inputPolicy: 'signature + "\\n\\nDescription: " + description',
12134
+ storesEmbeddingBase64: true,
12135
+ defaultRunMode: 'blocked-until-confirmed'
12136
+ };
12137
+ }
12138
+
12139
+ function normalizeConceptEmbeddingRequest(request = {}) {
12140
+ const signature = clampEvidenceText(request.signature || request.Signature, 500);
12141
+ const description = clampEvidenceText(request.description || request.Description, 2400);
12142
+ if (!signature.trim()) {
12143
+ const err = new Error('signature is required');
12144
+ err.statusCode = 400;
12145
+ throw err;
12146
+ }
12147
+ if (!description.trim()) {
12148
+ const err = new Error('description is required');
12149
+ err.statusCode = 400;
12150
+ throw err;
12151
+ }
12152
+ return {
12153
+ signature: signature.trim(),
12154
+ description: description.trim(),
12155
+ category: clampEvidenceText(request.category || request.Category || '', 160),
12156
+ conceptType: clampEvidenceText(request.conceptType || request.ConceptType || 'Axiom', 80) || 'Axiom'
12157
+ };
12158
+ }
12159
+
12160
+ async function callConceptEmbeddingProvider(input, config) {
12161
+ const controller = new AbortController();
12162
+ const timeout = setTimeout(() => controller.abort(), 45000);
12163
+ try {
12164
+ const response = await fetch(`${config.baseUrl}/embeddings`, {
12165
+ method: 'POST',
12166
+ headers: {
12167
+ 'Authorization': `Bearer ${config.apiKey}`,
12168
+ 'Content-Type': 'application/json'
12169
+ },
12170
+ body: JSON.stringify({ model: config.model, input }),
12171
+ signal: controller.signal
12172
+ });
12173
+ const text = await response.text();
12174
+ if (!response.ok) {
12175
+ const err = new Error(`OpenAI-compatible embeddings error ${response.status}: ${text.slice(0, 500)}`);
12176
+ err.statusCode = 502;
12177
+ throw err;
12178
+ }
12179
+ let payload;
12180
+ try {
12181
+ payload = text ? JSON.parse(text) : {};
12182
+ } catch (parseErr) {
12183
+ const err = new Error(`Embedding provider returned invalid JSON: ${parseErr?.message || parseErr}`);
12184
+ err.statusCode = 502;
12185
+ throw err;
12186
+ }
12187
+ const embedding = payload?.data?.[0]?.embedding;
12188
+ if (!Array.isArray(embedding) || embedding.length === 0) {
12189
+ const err = new Error('Embedding provider returned an empty embedding.');
12190
+ err.statusCode = 502;
12191
+ throw err;
12192
+ }
12193
+ if (embedding.length > 16384) {
12194
+ const err = new Error(`Embedding vector too large: ${embedding.length}`);
12195
+ err.statusCode = 413;
12196
+ throw err;
12197
+ }
12198
+ return embedding.map(value => Number(value) || 0);
12199
+ } finally {
12200
+ clearTimeout(timeout);
12201
+ }
12202
+ }
12203
+
12204
+ async function upsertConceptEmbeddingRecord(request = {}) {
12205
+ const normalized = normalizeConceptEmbeddingRequest(request);
12206
+ const config = getConceptEmbeddingProviderConfig();
12207
+ if (!config.confirmed) {
12208
+ const err = new Error(`Embedding provider calls require MINDEXEC_CONCEPT_EMBED_LIVE_CONFIRM=${CONCEPT_EMBED_LIVE_CONFIRM_VALUE}`);
12209
+ err.statusCode = 403;
12210
+ throw err;
12211
+ }
12212
+ if (!config.hasApiKey) {
12213
+ const err = new Error('Embedding provider API key is missing from server environment.');
12214
+ err.statusCode = 403;
12215
+ throw err;
12216
+ }
12217
+
12218
+ const id = conceptHash64Hex(normalized.signature);
12219
+ let existing = null;
12220
+ try {
12221
+ existing = await readConceptCompositeRecordById(id);
12222
+ } catch (err) {
12223
+ if (Number(err?.statusCode) !== 404) throw err;
12224
+ }
12225
+
12226
+ const input = `${normalized.signature}\n\nDescription: ${normalized.description}`;
12227
+ const vector = await callConceptEmbeddingProvider(input, config);
12228
+ const nowUtc = new Date().toISOString();
12229
+ const { baseConceptDir, rowDir, indexPath } = getConceptStorePaths();
12230
+ const fileName = existing?.Path
12231
+ ? path.basename(existing.Path)
12232
+ : `${id.slice(2)}-${slugifyEvidence(normalized.signature, 64)}.json`;
12233
+ const fullPath = existing?.Path
12234
+ ? path.resolve(workspacePath, existing.Path)
12235
+ : path.resolve(rowDir, fileName);
12236
+
12237
+ if (!isPathWithin(baseConceptDir, fullPath) || !isPathWithin(baseConceptDir, indexPath)) {
12238
+ const err = new Error('Concept embedding path must stay under the concept cache.');
12239
+ err.statusCode = 400;
12240
+ throw err;
12241
+ }
12242
+
12243
+ const relativePath = normalizePathForClient(path.relative(workspacePath, fullPath));
12244
+ const relativeIndexPath = normalizePathForClient(path.relative(workspacePath, indexPath));
12245
+ const previousConcept = existing?.Concept || {};
12246
+ const conceptRow = {
12247
+ Id: id,
12248
+ SqlKey: conceptSqlKeyString(id),
12249
+ Signature: normalized.signature,
12250
+ Body: previousConcept.Body,
12251
+ Category: normalized.category || previousConcept.Category || '',
12252
+ ConceptType: normalized.conceptType || previousConcept.ConceptType || 'Axiom',
12253
+ CreatedUtc: previousConcept.CreatedUtc || nowUtc,
12254
+ UpdatedUtc: nowUtc,
12255
+ Description: normalized.description,
12256
+ EmbeddingVector: vector,
12257
+ EmbeddingBase64: serializeConceptFloatVectorBase64(vector),
12258
+ EmbeddingModel: config.model,
12259
+ EmbeddingUpdatedUtc: nowUtc,
12260
+ AtomCount: Number(previousConcept.AtomCount || 0),
12261
+ LiteralCount: Number(previousConcept.LiteralCount || 0)
12262
+ };
12263
+ const record = {
12264
+ Schema: 'MindExecution.Kernel.Store.ConceptConcept/v1',
12265
+ Store: {
12266
+ Provider: 'LocalBridgeJsonConceptStore',
12267
+ OriginalTable: 'tbl_concepts',
12268
+ Notes: 'OpenAI-compatible embedding provider result stored as JSON row projection and mirrored into native SQLite tbl_concepts.'
12269
+ },
12270
+ HashAlgorithm: CONCEPT_HASH_ALGORITHM,
12271
+ Concept: conceptRow,
12272
+ Path: relativePath,
12273
+ IndexPath: relativeIndexPath
12274
+ };
12275
+
12276
+ const unsignedJson = JSON.stringify(record, null, 2);
12277
+ record.Sha256 = crypto.createHash('sha256').update(unsignedJson, 'utf8').digest('hex');
12278
+ await writeFileAtomically(fullPath, `${JSON.stringify(record, null, 2)}\n`, 'utf8');
12279
+
12280
+ const currentIndex = await readJsonIfExists(indexPath, {
12281
+ Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
12282
+ Store: 'LocalBridgeJsonConceptStore',
12283
+ HashAlgorithm: CONCEPT_HASH_ALGORITHM,
12284
+ Rows: []
12285
+ });
12286
+ const rows = Array.isArray(currentIndex.Rows) ? currentIndex.Rows : [];
12287
+ const nextRows = [
12288
+ {
12289
+ Id: conceptRow.Id,
12290
+ SqlKey: conceptRow.SqlKey,
12291
+ Signature: conceptRow.Signature,
12292
+ Category: conceptRow.Category,
12293
+ ConceptType: conceptRow.ConceptType,
12294
+ UpdatedUtc: conceptRow.UpdatedUtc,
12295
+ AtomCount: conceptRow.AtomCount,
12296
+ LiteralCount: conceptRow.LiteralCount,
12297
+ Path: relativePath,
12298
+ Sha256: record.Sha256,
12299
+ EmbeddingModel: conceptRow.EmbeddingModel,
12300
+ EmbeddingUpdatedUtc: conceptRow.EmbeddingUpdatedUtc
12301
+ },
12302
+ ...rows.filter(row => String(row?.Id || '').toLowerCase() !== conceptRow.Id)
12303
+ ].slice(0, 512);
12304
+ const nextIndex = {
12305
+ Schema: 'MindExecution.Kernel.Store.ConceptConceptIndex/v1',
12306
+ Store: 'LocalBridgeJsonConceptStore',
12307
+ HashAlgorithm: CONCEPT_HASH_ALGORITHM,
12308
+ UpdatedUtc: nowUtc,
12309
+ RowCount: nextRows.length,
12310
+ Rows: nextRows
12311
+ };
12312
+ await writeFileAtomically(indexPath, `${JSON.stringify(nextIndex, null, 2)}\n`, 'utf8');
12313
+ record.NativeSqlite = await upsertConceptNativeSqlite(record);
12314
+ return record;
12315
+ }
12316
+
12317
+ function parseHtmlAttributes(attrs) {
11090
12318
  const result = {};
11091
12319
  const regex = /([A-Za-z_:][-A-Za-z0-9_:.]*)\s*=\s*["']([^"']*)["']/g;
11092
12320
  let match;
@@ -12644,9 +13872,9 @@ app.post('/api/web/search', async (req, res) => {
12644
13872
  }
12645
13873
  });
12646
13874
 
12647
- app.post('/api/web/fetch', async (req, res) => {
12648
- try {
12649
- const { url, maxChars = 12000 } = req.body || {};
13875
+ app.post('/api/web/fetch', async (req, res) => {
13876
+ try {
13877
+ const { url, maxChars = 12000 } = req.body || {};
12650
13878
  if (!url || !String(url).trim()) {
12651
13879
  return res.status(400).json({ error: 'URL is required' });
12652
13880
  }
@@ -12662,12 +13890,119 @@ app.post('/api/web/fetch', async (req, res) => {
12662
13890
  console.error('[Web/Fetch] Error:', err);
12663
13891
  const statusCode = Number(err?.statusCode) || 500;
12664
13892
  res.status(statusCode).json({ error: err?.message || 'Web fetch failed' });
12665
- }
12666
- });
12667
-
12668
- app.post('/api/browser/open', async (req, res) => {
12669
- try {
12670
- const { url } = req.body || {};
13893
+ }
13894
+ });
13895
+
13896
+ app.post('/api/evidence/save', async (req, res) => {
13897
+ try {
13898
+ const record = await saveEvidenceRecord(req.body || {});
13899
+ logToolAction(
13900
+ 'Evidence.Save',
13901
+ `${formatKeyValue('path', tone(record.Path, 'path'))} ${formatKeyValue('kind', record.Kind)} ${formatKeyValue('source', shortenText(record.SourceUrl || record.SourcePath || '-', 100))}`,
13902
+ 'success');
13903
+ res.json(buildEvidenceResponse(record));
13904
+ } catch (err) {
13905
+ console.error('[Evidence/Save] Error:', err);
13906
+ const statusCode = Number(err?.statusCode) || 500;
13907
+ res.status(statusCode).json({ success: false, error: err?.message || 'Evidence save failed' });
13908
+ }
13909
+ });
13910
+
13911
+ app.post('/api/concept/define-composite', async (req, res) => {
13912
+ try {
13913
+ const record = await saveConceptCompositeRecord(req.body || {});
13914
+ logToolAction(
13915
+ 'Concept.DefineComposite',
13916
+ `${formatKeyValue('id', record.Concept.Id)} ${formatKeyValue('path', tone(record.Path, 'path'))} ${formatKeyValue('atoms', record.Concept.AtomCount)}`,
13917
+ 'success');
13918
+ res.json(buildConceptCompositeResponse(record));
13919
+ } catch (err) {
13920
+ console.error('[Concept/DefineComposite] Error:', err);
13921
+ const statusCode = Number(err?.statusCode) || 500;
13922
+ res.status(statusCode).json({ success: false, error: err?.message || 'Concept composite save failed' });
13923
+ }
13924
+ });
13925
+
13926
+ app.get('/api/concept/status', async (req, res) => {
13927
+ try {
13928
+ const index = await readConceptStoreIndex();
13929
+ const nativeSqlite = await readConceptNativeSqliteStatus();
13930
+ const response = buildConceptStoreStatusResponse(index, nativeSqlite);
13931
+ logToolAction(
13932
+ 'Concept.Status',
13933
+ `${formatKeyValue('rows', response.rowCount)} ${formatKeyValue('store', response.adapterState)} ${formatKeyValue('sqlite', response.nativeSqliteAdapterState)} ${formatKeyValue('index', tone(response.indexPath || '-', 'path'))}`,
13934
+ response.adapterState === 'json-row-projection' ? 'bridge' : 'warn');
13935
+ res.json(response);
13936
+ } catch (err) {
13937
+ console.error('[Concept/Status] Error:', err);
13938
+ const statusCode = Number(err?.statusCode) || 500;
13939
+ res.status(statusCode).json({ success: false, error: err?.message || 'Concept status failed' });
13940
+ }
13941
+ });
13942
+
13943
+ app.get('/api/concept/row', async (req, res) => {
13944
+ try {
13945
+ const record = await readConceptCompositeRecordById(req.query?.id || req.query?.Id);
13946
+ logToolAction(
13947
+ 'Concept.Row',
13948
+ `${formatKeyValue('id', record.Concept.Id)} ${formatKeyValue('path', tone(record.Path, 'path'))} ${formatKeyValue('atoms', record.Concept.AtomCount)}`,
13949
+ 'bridge');
13950
+ res.json(buildConceptCompositeResponse(record));
13951
+ } catch (err) {
13952
+ console.error('[Concept/Row] Error:', err);
13953
+ const statusCode = Number(err?.statusCode) || 500;
13954
+ res.status(statusCode).json({ success: false, error: err?.message || 'Concept row read failed' });
13955
+ }
13956
+ });
13957
+
13958
+ app.get('/api/concept/sqlite/row', async (req, res) => {
13959
+ try {
13960
+ const response = await readConceptNativeSqliteRowById(req.query?.id || req.query?.Id);
13961
+ logToolAction(
13962
+ 'Concept.SQLite.Row',
13963
+ `${formatKeyValue('id', response.id)} ${formatKeyValue('path', tone(response.sqlitePath, 'path'))} ${formatKeyValue('bytes', response.embeddingBytes)}`,
13964
+ 'bridge');
13965
+ res.json(response);
13966
+ } catch (err) {
13967
+ console.error('[Concept/SQLite/Row] Error:', err);
13968
+ const statusCode = Number(err?.statusCode) || 500;
13969
+ res.status(statusCode).json({ success: false, error: err?.message || 'Concept SQLite row read failed' });
13970
+ }
13971
+ });
13972
+
13973
+ app.get('/api/concept/embed/readiness', async (req, res) => {
13974
+ try {
13975
+ const response = buildConceptEmbeddingReadinessResponse();
13976
+ logToolAction(
13977
+ 'Concept.Embed.Readiness',
13978
+ `${formatKeyValue('state', response.adapterState)} ${formatKeyValue('model', response.model)} ${formatKeyValue('endpoint', `${response.baseUrlHost}${response.endpointPath}`)}`,
13979
+ response.adapterState === 'available-opt-in' ? 'bridge' : 'warn');
13980
+ res.json(response);
13981
+ } catch (err) {
13982
+ console.error('[Concept/Embed/Readiness] Error:', err);
13983
+ const statusCode = Number(err?.statusCode) || 500;
13984
+ res.status(statusCode).json({ success: false, error: err?.message || 'Concept embed readiness failed' });
13985
+ }
13986
+ });
13987
+
13988
+ app.post('/api/concept/embed', async (req, res) => {
13989
+ try {
13990
+ const record = await upsertConceptEmbeddingRecord(req.body || {});
13991
+ logToolAction(
13992
+ 'Concept.Embed',
13993
+ `${formatKeyValue('id', record.Concept.Id)} ${formatKeyValue('dim', Array.isArray(record.Concept.EmbeddingVector) ? record.Concept.EmbeddingVector.length : 0)} ${formatKeyValue('model', record.Concept.EmbeddingModel)}`,
13994
+ 'success');
13995
+ res.json(buildConceptCompositeResponse(record));
13996
+ } catch (err) {
13997
+ console.error('[Concept/Embed] Error:', err);
13998
+ const statusCode = Number(err?.statusCode) || 500;
13999
+ res.status(statusCode).json({ success: false, error: err?.message || 'Concept embed failed' });
14000
+ }
14001
+ });
14002
+
14003
+ app.post('/api/browser/open', async (req, res) => {
14004
+ try {
14005
+ const { url } = req.body || {};
12671
14006
  if (!url || !String(url).trim()) {
12672
14007
  return res.status(400).json({ error: 'URL is required' });
12673
14008
  }