@kedem/okdb 1.0.1 → 1.0.4

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 (142) hide show
  1. package/bin/okdb.js +1 -1
  2. package/keys/public.pem +3 -0
  3. package/okdb.js +1 -1
  4. package/package.json +2 -2
  5. package/public/admin-app.js +1 -1
  6. package/public/components/admin-route-host.ok.js +1 -1
  7. package/public/components/env-picker.ok.js +1 -1
  8. package/public/components/field-path-input.ok.js +1 -1
  9. package/public/components/field.html +154 -2
  10. package/public/components/geo-map.ok.js +1 -1
  11. package/public/components/ok-cron-input.ok.js +1 -1
  12. package/public/components/ok-dropzone.ok.js +1 -1
  13. package/public/components/ok-js-input.ok.js +1 -1
  14. package/public/components/ok-json-input.ok.js +1 -1
  15. package/public/components/ok-text-monaco-input.ok.js +1 -1
  16. package/public/components/theme-toggle.ok.js +1 -1
  17. package/public/index.html +29 -2
  18. package/public/layouts/_default.ok.html +1 -1
  19. package/public/layouts/okdb-cube.ok.html +1 -1
  20. package/public/login-app.js +1 -1
  21. package/public/login.html +205 -1
  22. package/public/modules/ok.js +1 -1
  23. package/public/sections/api/index.ok.html +1 -1
  24. package/public/sections/api/parts/api-endpoint.ok.js +1 -1
  25. package/public/sections/auth/index.ok.html +1 -1
  26. package/public/sections/auth/modals/create-token-modal.ok.js +1 -1
  27. package/public/sections/auth/modals/edit-token-modal.ok.js +1 -1
  28. package/public/sections/auth/modals/perm-info-popover.ok.js +1 -1
  29. package/public/sections/auth/parts/token-detail.ok.js +1 -1
  30. package/public/sections/auth/parts/token-list.ok.js +1 -1
  31. package/public/sections/db/index.ok.html +1 -1
  32. package/public/sections/db/modals/add-item-modal.ok.js +1 -1
  33. package/public/sections/db/modals/create-env-modal.ok.js +1 -1
  34. package/public/sections/db/modals/create-fts-modal.ok.js +1 -1
  35. package/public/sections/db/modals/create-index-modal.ok.js +1 -1
  36. package/public/sections/db/modals/create-pipeline-modal.ok.js +1 -1
  37. package/public/sections/db/modals/demo-env-modal.ok.js +1 -1
  38. package/public/sections/db/modals/remove-env-modal.ok.js +1 -1
  39. package/public/sections/db/modals/schema-edit-modal.ok.js +1 -1
  40. package/public/sections/db/parts/db-overview.ok.js +1 -1
  41. package/public/sections/db/parts/db-pipelines-panel.ok.js +1 -1
  42. package/public/sections/db/parts/edit-row.ok.js +1 -1
  43. package/public/sections/db/parts/tm-timeline.ok.js +1 -1
  44. package/public/sections/db/parts/type-changelog.ok.js +1 -1
  45. package/public/sections/db/parts/type-list.ok.js +1 -1
  46. package/public/sections/db/parts/type-pipelines-tab.ok.js +1 -1
  47. package/public/sections/db/parts/type-schema-tab.ok.js +1 -1
  48. package/public/sections/db/parts/type-viewer.ok.js +1 -1
  49. package/public/sections/db/parts/type-violations-tab.ok.js +1 -1
  50. package/public/sections/docs/index.ok.html +1 -1
  51. package/public/sections/embeddings/index.ok.html +1 -1
  52. package/public/sections/embeddings/modals/register-model-modal.ok.js +1 -1
  53. package/public/sections/embeddings/parts/embed-create-panel.ok.js +1 -1
  54. package/public/sections/embeddings/parts/embed-embedder-panel.ok.js +1 -1
  55. package/public/sections/embeddings/parts/embed-engine-declaration-editor.ok.js +1 -1
  56. package/public/sections/embeddings/parts/embed-engine-list.ok.js +1 -1
  57. package/public/sections/embeddings/parts/embed-indexer-panel.ok.js +1 -1
  58. package/public/sections/embeddings/parts/embed-lifecycle-bar.ok.js +1 -1
  59. package/public/sections/embeddings/parts/embed-model-catalog.ok.js +1 -1
  60. package/public/sections/embeddings/parts/embed-overview.ok.js +1 -1
  61. package/public/sections/embeddings/parts/embed-search-panel.ok.js +1 -1
  62. package/public/sections/embeddings/parts/embed-worker-panel.ok.js +1 -1
  63. package/public/sections/embeddings/parts/embeddings-engine-panel.ok.js +1 -1
  64. package/public/sections/embeddings/parts/engines-overview.ok.js +1 -1
  65. package/public/sections/embeddings/parts/pipeline-create-panel.ok.js +1 -1
  66. package/public/sections/engines/engine-panel-shared-style.js +1 -1
  67. package/public/sections/engines/engine-ui-utils.js +1 -1
  68. package/public/sections/engines/index.ok.html +1 -1
  69. package/public/sections/engines/modals/engine-modal.ok.js +1 -1
  70. package/public/sections/engines/parts/engine-declaration-editor.ok.js +1 -1
  71. package/public/sections/engines/parts/engine-lifecycle-actions.ok.js +1 -1
  72. package/public/sections/engines/parts/engine-panel-shell.ok.js +1 -1
  73. package/public/sections/engines/parts/engine-resource-card.ok.js +1 -1
  74. package/public/sections/engines/parts/engine-row-item.ok.js +1 -1
  75. package/public/sections/engines/parts/generic-engine-panel.ok.js +1 -1
  76. package/public/sections/files/index.ok.html +1 -1
  77. package/public/sections/files/parts/files-blob-status.ok.js +1 -1
  78. package/public/sections/files/parts/files-collection-list.ok.js +1 -1
  79. package/public/sections/files/parts/files-collection-panel.ok.js +1 -1
  80. package/public/sections/files/parts/files-file-list.ok.js +1 -1
  81. package/public/sections/files/parts/files-overview.ok.js +1 -1
  82. package/public/sections/files/parts/files-path-browser.ok.js +1 -1
  83. package/public/sections/files/parts/files-upload-panel.ok.js +1 -1
  84. package/public/sections/functions/index.ok.html +1 -1
  85. package/public/sections/functions/modals/function-modal.ok.js +1 -1
  86. package/public/sections/functions/parts/function-detail.ok.js +1 -1
  87. package/public/sections/functions/parts/function-logs.ok.js +1 -1
  88. package/public/sections/functions/parts/function-runner.ok.js +1 -1
  89. package/public/sections/functions/parts/functions-list.ok.js +1 -1
  90. package/public/sections/license/index.ok.html +1 -1
  91. package/public/sections/license/parts/license-panel.ok.js +1 -1
  92. package/public/sections/processors/index.ok.html +1 -1
  93. package/public/sections/queue/index.ok.html +1 -1
  94. package/public/sections/queue/modals/create-bucket-modal.ok.js +1 -1
  95. package/public/sections/queue/modals/edit-bucket-modal.ok.js +1 -1
  96. package/public/sections/queue/modals/edit-job-modal.ok.js +1 -1
  97. package/public/sections/queue/modals/enqueue-job-modal.ok.js +1 -1
  98. package/public/sections/queue/modals/job-type-modal.ok.js +1 -1
  99. package/public/sections/queue/parts/ok-job-form.ok.js +1 -1
  100. package/public/sections/queue/parts/queue-buckets.ok.js +1 -1
  101. package/public/sections/queue/parts/queue-job-types.ok.js +1 -1
  102. package/public/sections/queue/parts/queue-jobs.ok.js +1 -1
  103. package/public/sections/queue/parts/queue-types.ok.js +1 -1
  104. package/public/sections/queue/parts/queue-workers.ok.js +1 -1
  105. package/public/sections/sync/index.ok.html +1 -1
  106. package/public/sections/sync/parts/sync-node-detail.ok.js +1 -1
  107. package/public/sections/sync/parts/sync-retention.ok.js +1 -1
  108. package/public/sections/sync/parts/sync-topology.ok.js +1 -1
  109. package/public/sections/system/index.ok.html +1 -1
  110. package/public/sections/system/modals/data-ops-modal.ok.js +1 -1
  111. package/public/sections/system/parts/system-api-panel.ok.js +1 -1
  112. package/public/sections/system/parts/system-auth-panel.ok.js +1 -1
  113. package/public/sections/system/parts/system-log-history.ok.js +1 -1
  114. package/public/sections/system/parts/system-log.ok.js +1 -1
  115. package/public/sections/system/parts/system-status.ok.js +1 -1
  116. package/public/sections/system/parts/system-sync-panel.ok.js +1 -1
  117. package/public/sections/views/index.ok.html +1 -1
  118. package/public/sections/views/modals/create-view-modal.ok.js +1 -1
  119. package/public/sections/views/parts/view-detail.ok.js +1 -1
  120. package/public/sections/views/parts/views-list.ok.js +1 -1
  121. package/public/sections/views/parts/views-overview.ok.js +1 -1
  122. package/public/setup-app.js +1 -1
  123. package/public/setup.html +189 -1
  124. package/public/stores/auth-store.js +1 -1
  125. package/public/stores/events-store.js +1 -1
  126. package/public/stores/functions-store.js +1 -1
  127. package/public/stores/okdb-store.js +1 -1
  128. package/public/stores/theme-store.js +1 -1
  129. package/public/test-cron-input.html +53 -3
  130. package/public/test-json-input.html +182 -3
  131. package/public/util/permissions.js +1 -1
  132. package/public/util/sift-schema.js +1 -1
  133. package/public/vendor/okjs/ok.esm.min.js +1 -2
  134. package/public/view-models/type-query-vm.js +1 -1
  135. package/okdb-data/default/data.mdb +0 -0
  136. package/okdb-data/default/lock.mdb +0 -0
  137. package/okdb-data/~log/data.mdb +0 -0
  138. package/okdb-data/~log/lock.mdb +0 -0
  139. package/okdb-data/~system/data.mdb +0 -0
  140. package/okdb-data/~system/lock.mdb +0 -0
  141. package/public/images/logo.png +0 -0
  142. package/public/images/logo.svg +0 -333
@@ -1 +1 @@
1
- const _0x1481a9=_0x122b;function _0x122b(_0x4d16f0,_0x6bd327){_0x4d16f0=_0x4d16f0-0x9d;const _0x2677c4=_0x2677();let _0x122bcb=_0x2677c4[_0x4d16f0];return _0x122bcb;}(function(_0x12015f,_0x312e90){const _0x11c935=_0x122b,_0xccb8b8=_0x12015f();while(!![]){try{const _0x12bddb=parseInt(_0x11c935(0xbd))/0x1*(-parseInt(_0x11c935(0xaf))/0x2)+-parseInt(_0x11c935(0xa8))/0x3*(parseInt(_0x11c935(0xa1))/0x4)+-parseInt(_0x11c935(0xc8))/0x5*(parseInt(_0x11c935(0xbf))/0x6)+-parseInt(_0x11c935(0xb8))/0x7*(parseInt(_0x11c935(0x9e))/0x8)+-parseInt(_0x11c935(0xb3))/0x9+parseInt(_0x11c935(0xb7))/0xa+parseInt(_0x11c935(0xa2))/0xb*(parseInt(_0x11c935(0xb1))/0xc);if(_0x12bddb===_0x312e90)break;else _0xccb8b8['push'](_0xccb8b8['shift']());}catch(_0x1a4516){_0xccb8b8['push'](_0xccb8b8['shift']());}}}(_0x2677,0x3db43));function _0x2677(){const _0x3cfad1=['round','violations','status','122JLgNeS','violationsBusy','408hvFjVv','errorCount','1723860HovfVU','$attr','envApiBase','/violations/','3285530YBSNLQ','385xQXOLP','loadViolations','\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-count-badge\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20margin-left:\x206px;\x0a\x20\x20\x20\x20\x20\x20\x20\x20font-size:\x2010px;\x0a\x20\x20\x20\x20\x20\x20\x20\x20padding:\x202px\x208px;\x0a\x20\x20\x20\x20\x20\x20\x20\x20border-radius:\x20999px;\x0a\x20\x20\x20\x20\x20\x20\x20\x20border:\x201px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-danger)\x2033%,\x20transparent);\x0a\x20\x20\x20\x20\x20\x20\x20\x20color:\x20var(--okdb-danger);\x0a\x20\x20\x20\x20\x20\x20\x20\x20font-weight:\x20600;\x0a\x20\x20\x20\x20\x20\x20\x20\x20text-transform:\x20none;\x0a\x20\x20\x20\x20\x20\x20\x20\x20letter-spacing:\x200;\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-table\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20display:\x20grid;\x0a\x20\x20\x20\x20\x20\x20\x20\x20grid-template-columns:\x20minmax(120px,\x202fr)\x2060px\x2090px\x20auto;\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-hd\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20font-size:\x2011px;\x0a\x20\x20\x20\x20\x20\x20\x20\x20opacity:\x20.4;\x0a\x20\x20\x20\x20\x20\x20\x20\x20padding:\x200\x2012px\x206px\x200;\x0a\x20\x20\x20\x20\x20\x20\x20\x20border-bottom:\x201px\x20solid\x20var(--okdb-app-border);\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-cell\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20display:\x20flex;\x0a\x20\x20\x20\x20\x20\x20\x20\x20align-items:\x20center;\x0a\x20\x20\x20\x20\x20\x20\x20\x20padding:\x207px\x2012px\x207px\x200;\x0a\x20\x20\x20\x20\x20\x20\x20\x20border-bottom:\x201px\x20solid\x20var(--okdb-app-surface);\x0a\x20\x20\x20\x20\x20\x20\x20\x20cursor:\x20pointer;\x0a\x20\x20\x20\x20\x20\x20\x20\x20transition:\x20background\x20.1s;\x0a\x20\x20\x20\x20\x20\x20\x20\x20min-width:\x200;\x0a\x20\x20\x20\x20\x20\x20\x20\x20overflow:\x20hidden;\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-cell:hover\x20{\x20background:\x20#ffffff07;\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-key\x20{\x20overflow:\x20hidden;\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-key\x20span\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20overflow:\x20hidden;\x0a\x20\x20\x20\x20\x20\x20\x20\x20text-overflow:\x20ellipsis;\x0a\x20\x20\x20\x20\x20\x20\x20\x20white-space:\x20nowrap;\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-expanded\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20padding:\x2010px\x2012px\x2012px\x2014px;\x0a\x20\x20\x20\x20\x20\x20\x20\x20background:\x20var(--okdb-app-bg-deep);\x0a\x20\x20\x20\x20\x20\x20\x20\x20border-bottom:\x201px\x20solid\x20var(--okdb-app-surface);\x0a\x20\x20\x20\x20\x20\x20\x20\x20display:\x20flex;\x0a\x20\x20\x20\x20\x20\x20\x20\x20flex-direction:\x20column;\x0a\x20\x20\x20\x20\x20\x20\x20\x20gap:\x204px;\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-err-row\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20display:\x20flex;\x0a\x20\x20\x20\x20\x20\x20\x20\x20gap:\x2010px;\x0a\x20\x20\x20\x20\x20\x20\x20\x20align-items:\x20baseline;\x0a\x20\x20\x20\x20\x20\x20\x20\x20flex-wrap:\x20wrap;\x0a\x20\x20\x20\x20\x20\x20\x20\x20padding:\x204px\x200;\x0a\x20\x20\x20\x20\x20\x20\x20\x20border-bottom:\x201px\x20solid\x20var(--okdb-app-surface-2);\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-err-row:last-child\x20{\x20border-bottom:\x20none;\x20}\x0a\x20\x20\x20\x20\x20\x20type-violations-tab\x20.tv-path\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20font-size:\x2011px;\x0a\x20\x20\x20\x20\x20\x20\x20\x20color:\x20var(--okdb-danger);\x0a\x20\x20\x20\x20\x20\x20\x20\x20font-family:\x20monospace;\x0a\x20\x20\x20\x20\x20\x20\x20\x20white-space:\x20nowrap;\x0a\x20\x20\x20\x20\x20\x20\x20\x20flex-shrink:\x200;\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20','just\x20now','message','2593drFkUD','violationsError','47376ieuBRU','catch','errors','stores','result','toLocaleDateString','okdb','type-violations-tab','onViewKey','20amGRSX','$ok','49704ZsfWiV','error','json','4kuyiTp','246444SexWqk','type','s\x20ago','$watch','m\x20ago','length','343614GwAYqi','now','statusText','function'];_0x2677=function(){return _0x3cfad1;};return _0x2677();}import _0x3b0778 from'@toolkit/elements/ok-icon.ok.js';export default{'tag':_0x1481a9(0xc6),'dependencies':[_0x3b0778],'attr':{'type':{},'onViewKey':{}},'context':_0x5d8f94=>({'violations':[],'violationsBusy':!0x1,'violationsError':null,'expandedViolation':null,get 'type'(){const _0x529c43=_0x1481a9;return _0x5d8f94[_0x529c43(0xb4)]['type'];},get 'envApiBase'(){const _0x3909f7=_0x1481a9;return _0x5d8f94[_0x3909f7(0x9d)][_0x3909f7(0xc2)][_0x3909f7(0xc5)]['apiBase'];},async 'loadViolations'(){const _0x4986c0=_0x1481a9;if(this['type']){this[_0x4986c0(0xb0)]=!0x0,this[_0x4986c0(0xbe)]=null;try{const _0x4eb76a=await fetch(this[_0x4986c0(0xb5)]+_0x4986c0(0xb6)+encodeURIComponent(this[_0x4986c0(0xa3)]));if(0x194===_0x4eb76a[_0x4986c0(0xae)])return void(this['violations']=[]);if(!_0x4eb76a['ok']){const _0x29e4cf=await _0x4eb76a[_0x4986c0(0xa0)]()[_0x4986c0(0xc0)](()=>({}));throw new Error(_0x29e4cf?.[_0x4986c0(0x9f)]?.[_0x4986c0(0xbc)]||_0x4eb76a[_0x4986c0(0xaa)]);}const _0x443dd8=await _0x4eb76a[_0x4986c0(0xa0)]();this[_0x4986c0(0xad)]=_0x443dd8?.['data']?.[_0x4986c0(0xad)]??_0x443dd8?.[_0x4986c0(0xc3)]?.[_0x4986c0(0xad)]??[];}catch(_0x5b16d4){this[_0x4986c0(0xbe)]=_0x5b16d4[_0x4986c0(0xbc)]||'Failed\x20to\x20load\x20violations',this[_0x4986c0(0xad)]=[];}finally{this[_0x4986c0(0xb0)]=!0x1;}}},'toggleViolation'(_0x4fd74b){this['expandedViolation']=this['expandedViolation']===_0x4fd74b?null:_0x4fd74b;},'viewDocument'(_0x2355fb){const _0x4620d6=_0x1481a9,_0x1d6a02=_0x5d8f94[_0x4620d6(0xb4)][_0x4620d6(0xc7)];_0x4620d6(0xab)==typeof _0x1d6a02&&_0x1d6a02(_0x2355fb);},'relTime'(_0x5dc5f3){const _0x3ad440=_0x1481a9;if(!_0x5dc5f3)return'—';const _0x5c57d4=Date[_0x3ad440(0xa9)]()-_0x5dc5f3;return _0x5c57d4<0x1388?_0x3ad440(0xbb):_0x5c57d4<0xea60?Math['round'](_0x5c57d4/0x3e8)+_0x3ad440(0xa4):_0x5c57d4<0x36ee80?Math[_0x3ad440(0xac)](_0x5c57d4/0xea60)+_0x3ad440(0xa6):_0x5c57d4<0x5265c00?Math[_0x3ad440(0xac)](_0x5c57d4/0x36ee80)+'h\x20ago':new Date(_0x5dc5f3)[_0x3ad440(0xc4)]();},'errorCount':_0x11fbf4=>(_0x11fbf4[_0x1481a9(0xc1)]??[])[_0x1481a9(0xa7)]||(_0x11fbf4[_0x1481a9(0xb2)]??0x0)}),async 'init'(_0x3e565a){const _0x56d5b3=_0x1481a9;_0x3e565a[_0x56d5b3(0xa5)](()=>this['type'],async()=>{const _0x5c1fed=_0x56d5b3;this['violations']=[],this['expandedViolation']=null,this['type']&&await this[_0x5c1fed(0xb9)]();}),this['type']&&await this[_0x56d5b3(0xb9)]();},'template':'\x0a<div\x20style=\x22display:flex;\x20flex-direction:column;\x20gap:16px;\x20flex:1;\x20overflow:auto;\x20padding-right:4px;\x22>\x0a\x0a\x20\x20<div\x20class=\x22card\x22>\x0a\x20\x20\x20\x20<div\x20class=\x22manage-section-header\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22manage-section-title\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20Schema\x20Violations\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22violations.length\x20>\x200\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22tv-count-badge\x22>{{\x20violations.length\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20<button\x20@click=\x22loadViolations()\x22\x20:disabled=\x22violationsBusy\x22\x20class=\x22btn-icon\x22\x20style=\x22font-size:11px;\x20padding:3px\x2010px;\x20opacity:.75;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<ok-icon\x20name=\x22refresh-cw\x22></ok-icon>Refresh\x0a\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20<if\x20:=\x22violationsBusy\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22opacity:.45;\x20font-size:13px;\x22>Loading\x20violations…</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<if\x20:=\x22violationsError\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22color:var(--okdb-danger);\x20font-size:12px;\x20padding:8px\x2010px;\x20border-radius:8px;\x20border:1px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-danger)\x2020%,\x20transparent);\x20background:color-mix(in\x20srgb,\x20var(--okdb-danger)\x204%,\x20transparent);\x22>{{\x20violationsError\x20}}</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<if\x20:=\x22!violationsBusy\x20&&\x20!violationsError\x20&&\x20violations.length\x20===\x200\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22opacity:.4;\x20font-size:13px;\x22>No\x20violations\x20—\x20all\x20documents\x20conform\x20to\x20the\x20schema.</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<if\x20:=\x22violations.length\x20>\x200\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-table\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-hd\x22>Key</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-hd\x22>Errors</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-hd\x22>When</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-hd\x22></div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22violations\x22\x20let:item=\x22v\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-cell\x20tv-key\x22\x20@click=\x22toggleViolation(v.key)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-family:monospace;\x20font-size:12px;\x20color:var(--okdb-json-key);\x22>{{\x20v.key\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-cell\x22\x20@click=\x22toggleViolation(v.key)\x22\x20style=\x22font-size:12px;\x20opacity:.65;\x22>{{\x20errorCount(v)\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-cell\x22\x20@click=\x22toggleViolation(v.key)\x22\x20style=\x22font-size:11px;\x20opacity:.45;\x22>{{\x20relTime(v.timestamp)\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-cell\x22\x20style=\x22justify-content:flex-end;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22$attr.onViewKey\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@click:stop=\x22viewDocument(v.key)\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22btn-icon\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22font-size:11px;\x20padding:2px\x208px;\x20opacity:.75;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20title=\x22Switch\x20to\x20data\x20tab\x20for\x20this\x20document\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20>View\x20→</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22expandedViolation\x20===\x20v.key\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-expanded\x22\x20style=\x22grid-column:1/-1;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22(v.errors\x20??\x20[])\x22\x20let:item=\x22err\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22tv-err-row\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22tv-path\x22>{{\x20err.path\x20||\x20\x27/\x27\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:12px;\x20opacity:.85;\x20flex:1;\x20min-width:0;\x22>{{\x20err.message\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22err.expected\x20!=\x20null\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20opacity:.5;\x20white-space:nowrap;\x22>expected:\x20<code\x20style=\x22font-size:11px;\x22>{{\x20err.expected\x20}}</code></span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22err.actual\x20!=\x20null\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20opacity:.5;\x20white-space:nowrap;\x22>got:\x20<code\x20style=\x22font-size:11px;\x20color:var(--okdb-danger);\x22>{{\x20err.actual\x20}}</code></span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!(v.errors\x20??\x20[]).length\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:12px;\x20opacity:.4;\x20padding:4px\x200;\x22>No\x20error\x20details\x20stored.</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</if>\x0a\x20\x20</div>\x0a</div>\x0a','style':_0x1481a9(0xba)};
1
+ import n from"@toolkit/elements/ok-icon.ok.js";export default{tag:"type-violations-tab",dependencies:[n],attr:{type:{},onViewKey:{}},context:n=>({violations:[],violationsBusy:!1,violationsError:null,expandedViolation:null,get type(){return n.$attr.type},get envApiBase(){return n.$ok.stores.okdb.apiBase},async loadViolations(){if(this.type){this.violationsBusy=!0,this.violationsError=null;try{const n=await fetch(`${this.envApiBase}/violations/${encodeURIComponent(this.type)}`);if(404===n.status)return void(this.violations=[]);if(!n.ok){const t=await n.json().catch(()=>({}));throw new Error(t?.error?.message||n.statusText)}const t=await n.json();this.violations=t?.data?.violations??t?.result?.violations??[]}catch(n){this.violationsError=n.message||"Failed to load violations",this.violations=[]}finally{this.violationsBusy=!1}}},toggleViolation(n){this.expandedViolation=this.expandedViolation===n?null:n},viewDocument(t){const o=n.$attr.onViewKey;"function"==typeof o&&o(t)},relTime(n){if(!n)return"—";const t=Date.now()-n;return t<5e3?"just now":t<6e4?`${Math.round(t/1e3)}s ago`:t<36e5?`${Math.round(t/6e4)}m ago`:t<864e5?`${Math.round(t/36e5)}h ago`:new Date(n).toLocaleDateString()},errorCount:n=>(n.errors??[]).length||(n.errorCount??0)}),async init(n){n.$watch(()=>this.type,async()=>{this.violations=[],this.expandedViolation=null,this.type&&await this.loadViolations()}),this.type&&await this.loadViolations()},template:'\n<div style="display:flex; flex-direction:column; gap:16px; flex:1; overflow:auto; padding-right:4px;">\n\n <div class="card">\n <div class="manage-section-header">\n <div class="manage-section-title">\n Schema Violations\n <if :="violations.length > 0">\n <span class="tv-count-badge">{{ violations.length }}</span>\n </if>\n </div>\n <button @click="loadViolations()" :disabled="violationsBusy" class="btn-icon" style="font-size:11px; padding:3px 10px; opacity:.75;">\n <ok-icon name="refresh-cw"></ok-icon>Refresh\n </button>\n </div>\n\n <if :="violationsBusy">\n <div style="opacity:.45; font-size:13px;">Loading violations…</div>\n </if>\n\n <if :="violationsError">\n <div style="color:var(--okdb-danger); font-size:12px; padding:8px 10px; border-radius:8px; border:1px solid color-mix(in srgb, var(--okdb-danger) 20%, transparent); background:color-mix(in srgb, var(--okdb-danger) 4%, transparent);">{{ violationsError }}</div>\n </if>\n\n <if :="!violationsBusy && !violationsError && violations.length === 0">\n <div style="opacity:.4; font-size:13px;">No violations — all documents conform to the schema.</div>\n </if>\n\n <if :="violations.length > 0">\n <div class="tv-table">\n <div class="tv-hd">Key</div>\n <div class="tv-hd">Errors</div>\n <div class="tv-hd">When</div>\n <div class="tv-hd"></div>\n\n <each :of="violations" let:item="v">\n <div class="tv-cell tv-key" @click="toggleViolation(v.key)">\n <span style="font-family:monospace; font-size:12px; color:var(--okdb-json-key);">{{ v.key }}</span>\n </div>\n <div class="tv-cell" @click="toggleViolation(v.key)" style="font-size:12px; opacity:.65;">{{ errorCount(v) }}</div>\n <div class="tv-cell" @click="toggleViolation(v.key)" style="font-size:11px; opacity:.45;">{{ relTime(v.timestamp) }}</div>\n <div class="tv-cell" style="justify-content:flex-end;">\n <if :="$attr.onViewKey">\n <button\n @click:stop="viewDocument(v.key)"\n class="btn-icon"\n style="font-size:11px; padding:2px 8px; opacity:.75;"\n title="Switch to data tab for this document"\n >View →</button>\n </if>\n </div>\n\n <if :="expandedViolation === v.key">\n <div class="tv-expanded" style="grid-column:1/-1;">\n <each :of="(v.errors ?? [])" let:item="err">\n <div class="tv-err-row">\n <span class="tv-path">{{ err.path || \'/\' }}</span>\n <span style="font-size:12px; opacity:.85; flex:1; min-width:0;">{{ err.message }}</span>\n <if :="err.expected != null">\n <span style="font-size:11px; opacity:.5; white-space:nowrap;">expected: <code style="font-size:11px;">{{ err.expected }}</code></span>\n </if>\n <if :="err.actual != null">\n <span style="font-size:11px; opacity:.5; white-space:nowrap;">got: <code style="font-size:11px; color:var(--okdb-danger);">{{ err.actual }}</code></span>\n </if>\n </div>\n </each>\n <if :="!(v.errors ?? []).length">\n <div style="font-size:12px; opacity:.4; padding:4px 0;">No error details stored.</div>\n </if>\n </div>\n </if>\n </each>\n </div>\n </if>\n </div>\n</div>\n',style:"\n type-violations-tab .tv-count-badge {\n margin-left: 6px;\n font-size: 10px;\n padding: 2px 8px;\n border-radius: 999px;\n border: 1px solid color-mix(in srgb, var(--okdb-danger) 33%, transparent);\n color: var(--okdb-danger);\n font-weight: 600;\n text-transform: none;\n letter-spacing: 0;\n }\n type-violations-tab .tv-table {\n display: grid;\n grid-template-columns: minmax(120px, 2fr) 60px 90px auto;\n }\n type-violations-tab .tv-hd {\n font-size: 11px;\n opacity: .4;\n padding: 0 12px 6px 0;\n border-bottom: 1px solid var(--okdb-app-border);\n }\n type-violations-tab .tv-cell {\n display: flex;\n align-items: center;\n padding: 7px 12px 7px 0;\n border-bottom: 1px solid var(--okdb-app-surface);\n cursor: pointer;\n transition: background .1s;\n min-width: 0;\n overflow: hidden;\n }\n type-violations-tab .tv-cell:hover { background: #ffffff07; }\n type-violations-tab .tv-key { overflow: hidden; }\n type-violations-tab .tv-key span {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n type-violations-tab .tv-expanded {\n padding: 10px 12px 12px 14px;\n background: var(--okdb-app-bg-deep);\n border-bottom: 1px solid var(--okdb-app-surface);\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n type-violations-tab .tv-err-row {\n display: flex;\n gap: 10px;\n align-items: baseline;\n flex-wrap: wrap;\n padding: 4px 0;\n border-bottom: 1px solid var(--okdb-app-surface-2);\n }\n type-violations-tab .tv-err-row:last-child { border-bottom: none; }\n type-violations-tab .tv-path {\n font-size: 11px;\n color: var(--okdb-danger);\n font-family: monospace;\n white-space: nowrap;\n flex-shrink: 0;\n }\n "};
@@ -1 +1 @@
1
- <script type="module">import docViewer from"@toolkit/components/ok-doc-viewer.ok.js";export default{tag:"docs-index",unwrap:!0,dependencies:[docViewer],context:e=>({manifest:[],get currentFile(){const t=e.$vars.$route?.params?.["*"];return t?t.replace(/\.md$/,"")+".md":"index.md"},isActive(e){return this.currentFile===e},navigateTo(t){const o=t.replace(/\.md$/,"");this.anchor="",e.$vars.$router?.push("/docs/"+o)},onAnchorChange(e){this.anchor=e},anchor:""}),async init(e){try{const e=await fetch("/docs/manifest.json");this.manifest=await e.json()}catch(e){console.error("[docs] failed to load manifest:",e)}e.$watch(()=>e.$vars.$route?.params?.["*"],()=>{this.anchor=""})}}</script><template><component import="../../layouts/_default.ok.html"><template name="sidebar"><nav class="docs-nav" aria-label="Documentation navigation"><each :of="manifest" let:item="item"><if :="item.file"><button class="docs-nav__item docs-nav__item--standalone" :class="{ 'docs-nav__item--active': isActive(item.file) }" @click="navigateTo(item.file)" :title="item.label">{{ item.label }}</button></if><if :="item.children"><div class="docs-nav__group"><span class="docs-nav__group-label">{{ item.label }}</span><each :of="item.children" let:child="child"><button class="docs-nav__item" :class="{ 'docs-nav__item--active': isActive(child.file) }" @click="navigateTo(child.file)" :title="child.label">{{ child.label }}</button></each></div></if></each></nav></template><template name="default"><div class="docs-wrap"><ok-doc-viewer :blocks="[]" root="/docs/" prefix="#/docs/" :file="currentFile" :anchor="anchor" :manifest="manifest" sidebar-title="On this page" @anchor-change="onAnchorChange($event.detail)"/></div></template></component></template><style>.docs-wrap{margin:-20px -24px -6px;min-height:calc(100% + 26px)}.docs-wrap ok-doc-viewer{--ok_color-accent:var(--okdb-accent);--ok_color-fg:var(--okdb-app-fg);--ok_color-muted-fg:var(--okdb-app-fg-subtle);--ok_color-muted-border:var(--okdb-app-surface-2);--font-mono:'Cascadia Code','Fira Code','Consolas',monospace;display:block;min-height:100%}.docs-wrap ok-doc-viewer .md table{border-collapse:collapse;width:100%;margin:1.2rem 0;font-size:13px}.docs-wrap ok-doc-viewer .md td,.docs-wrap ok-doc-viewer .md th{border:1px solid var(--okdb-app-surface-2);padding:7px 12px;text-align:left}.docs-wrap ok-doc-viewer .md th{background:var(--okdb-app-surface-2);color:#8fc8e8;font-weight:600;font-size:12px;letter-spacing:.03em}.docs-wrap ok-doc-viewer .md tr:hover td{background:var(--okdb-app-surface)}.docs-wrap ok-doc-viewer .md a{color:var(--okdb-accent);text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);transition:border-color .15s,color .15s}.docs-wrap ok-doc-viewer .md a:hover{color:#7fd8ff;border-bottom-color:#7fd8ff88}.docs-wrap ok-doc-viewer .md code:not(pre code){background:var(--okdb-app-bg-deep);border:1px solid var(--okdb-app-border-subtle);color:var(--okdb-accent);padding:1px 6px;border-radius:4px;font-size:.9em}.docs-wrap ok-doc-viewer .md blockquote{border-left:3px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);margin:1rem 0;padding:6px 14px;background:var(--okdb-app-surface);border-radius:0 6px 6px 0;color:var(--okdb-app-fg-muted);font-style:italic}.docs-wrap ok-doc-viewer .ok-code-block{background:var(--okdb-app-bg-deep);border-color:var(--okdb-app-border)}.docs-wrap ok-doc-viewer .ok-code-block__header{background:var(--okdb-app-surface-2);color:var(--okdb-app-fg-muted);border-bottom-color:var(--okdb-app-border)}.docs-wrap ok-doc-viewer .ok-code-block .copy{color:var(--okdb-app-fg-muted)}.docs-wrap ok-doc-viewer .ok-code-block .copy:hover{color:var(--okdb-app-fg);background:color-mix(in srgb,var(--okdb-app-fg) 8%,transparent)}.docs-nav{display:flex;flex-direction:column;gap:1px;margin:-2px -10px;padding:2px 0}.docs-nav__item{display:block;width:100%;text-align:left;padding:5px 14px;border-radius:0;border:none;border-left:2px solid transparent;background:0 0;color:var(--okdb-app-fg-muted);font-size:12.5px;cursor:pointer;transition:color .13s,background .13s,border-color .13s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.55;letter-spacing:.01em}.docs-nav__item--standalone{font-weight:500;color:var(--okdb-app-fg-muted);margin-top:2px}.docs-nav__item:hover{background:var(--okdb-app-surface-2);color:var(--okdb-app-fg);border-left-color:var(--okdb-app-border-strong)}.docs-nav__item--active{background:var(--okdb-accent-soft-bg)!important;color:var(--okdb-accent)!important;border-left-color:var(--okdb-accent)!important;font-weight:500}.docs-nav__group{margin-top:6px;padding-top:4px;border-top:1px solid var(--okdb-app-surface)}.docs-nav__group-label{display:block;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--okdb-app-fg-faint);padding:4px 14px 5px;pointer-events:none;user-select:none}</style>
1
+ <script type="module">import t from"@toolkit/components/ok-doc-viewer.ok.js";export default{tag:"docs-index",unwrap:!0,dependencies:[t],context:t=>({manifest:[],get currentFile(){const e=t.$vars.$route?.params?.["*"];return e?e.replace(/\.md$/,"")+".md":"index.md"},isActive(t){return this.currentFile===t},navigateTo(e){const o=e.replace(/\.md$/,"");this.anchor="",t.$vars.$router?.push("/docs/"+o)},onAnchorChange(t){this.anchor=t},anchor:""}),async init(t){try{const t=await fetch("/docs/manifest.json");this.manifest=await t.json()}catch(t){console.error("[docs] failed to load manifest:",t)}t.$watch(()=>t.$vars.$route?.params?.["*"],()=>{this.anchor=""})}};</script><template><component import="../../layouts/_default.ok.html"><template name="sidebar"><nav class="docs-nav" aria-label="Documentation navigation"><each :of="manifest" let:item="item"><if :="item.file"><button class="docs-nav__item docs-nav__item--standalone" :class="{ 'docs-nav__item--active': isActive(item.file) }" @click="navigateTo(item.file)" :title="item.label">{{ item.label }}</button></if><if :="item.children"><div class="docs-nav__group"><span class="docs-nav__group-label">{{ item.label }}</span><each :of="item.children" let:child="child"><button class="docs-nav__item" :class="{ 'docs-nav__item--active': isActive(child.file) }" @click="navigateTo(child.file)" :title="child.label">{{ child.label }}</button></each></div></if></each></nav></template><template name="default"><div class="docs-wrap"><ok-doc-viewer :blocks="[]" root="/docs/" prefix="#/docs/" :file="currentFile" :anchor="anchor" :manifest="manifest" sidebar-title="On this page" @anchor-change="onAnchorChange($event.detail)"/></div></template></component></template><style>.docs-wrap{margin:-20px -24px -6px;min-height:calc(100% + 26px)}.docs-wrap ok-doc-viewer{--ok_color-accent:var(--okdb-accent);--ok_color-fg:var(--okdb-app-fg);--ok_color-muted-fg:var(--okdb-app-fg-subtle);--ok_color-muted-border:var(--okdb-app-surface-2);--font-mono:'Cascadia Code','Fira Code','Consolas',monospace;display:block;min-height:100%}.docs-wrap ok-doc-viewer .md table{border-collapse:collapse;width:100%;margin:1.2rem 0;font-size:13px}.docs-wrap ok-doc-viewer .md td,.docs-wrap ok-doc-viewer .md th{border:1px solid var(--okdb-app-surface-2);padding:7px 12px;text-align:left}.docs-wrap ok-doc-viewer .md th{background:var(--okdb-app-surface-2);color:#8fc8e8;font-weight:600;font-size:12px;letter-spacing:.03em}.docs-wrap ok-doc-viewer .md tr:hover td{background:var(--okdb-app-surface)}.docs-wrap ok-doc-viewer .md a{color:var(--okdb-accent);text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);transition:border-color .15s,color .15s}.docs-wrap ok-doc-viewer .md a:hover{color:#7fd8ff;border-bottom-color:#7fd8ff88}.docs-wrap ok-doc-viewer .md code:not(pre code){background:var(--okdb-app-bg-deep);border:1px solid var(--okdb-app-border-subtle);color:var(--okdb-accent);padding:1px 6px;border-radius:4px;font-size:.9em}.docs-wrap ok-doc-viewer .md blockquote{border-left:3px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);margin:1rem 0;padding:6px 14px;background:var(--okdb-app-surface);border-radius:0 6px 6px 0;color:var(--okdb-app-fg-muted);font-style:italic}.docs-wrap ok-doc-viewer .ok-code-block{background:var(--okdb-app-bg-deep);border-color:var(--okdb-app-border)}.docs-wrap ok-doc-viewer .ok-code-block__header{background:var(--okdb-app-surface-2);color:var(--okdb-app-fg-muted);border-bottom-color:var(--okdb-app-border)}.docs-wrap ok-doc-viewer .ok-code-block .copy{color:var(--okdb-app-fg-muted)}.docs-wrap ok-doc-viewer .ok-code-block .copy:hover{color:var(--okdb-app-fg);background:color-mix(in srgb,var(--okdb-app-fg) 8%,transparent)}.docs-nav{display:flex;flex-direction:column;gap:1px;margin:-2px -10px;padding:2px 0}.docs-nav__item{display:block;width:100%;text-align:left;padding:5px 14px;border-radius:0;border:none;border-left:2px solid transparent;background:0 0;color:var(--okdb-app-fg-muted);font-size:12.5px;cursor:pointer;transition:color .13s,background .13s,border-color .13s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.55;letter-spacing:.01em}.docs-nav__item--standalone{font-weight:500;color:var(--okdb-app-fg-muted);margin-top:2px}.docs-nav__item:hover{background:var(--okdb-app-surface-2);color:var(--okdb-app-fg);border-left-color:var(--okdb-app-border-strong)}.docs-nav__item--active{background:var(--okdb-accent-soft-bg)!important;color:var(--okdb-accent)!important;border-left-color:var(--okdb-accent)!important;font-weight:500}.docs-nav__group{margin-top:6px;padding-top:4px;border-top:1px solid var(--okdb-app-surface)}.docs-nav__group-label{display:block;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--okdb-app-fg-faint);padding:4px 14px 5px;pointer-events:none;user-select:none}</style>
@@ -1 +1 @@
1
- <script type="module">export default{tag:"embeddings-section-alias",unwrap:!0}</script><template><component import="../engines/index.ok.html"></component></template>
1
+ <script type="module">export default{tag:"embeddings-section-alias",unwrap:!0};</script><template><component import="../engines/index.ok.html"></component></template>
@@ -1 +1 @@
1
- function _0x3df0(_0x4ccadc,_0xedc894){_0x4ccadc=_0x4ccadc-0x191;const _0x5e70b5=_0x5e70();let _0x3df01c=_0x5e70b5[_0x4ccadc];return _0x3df01c;}const _0x1c74ae=_0x3df0;(function(_0x5270a7,_0x419884){const _0x314c0d=_0x3df0,_0x1c1202=_0x5270a7();while(!![]){try{const _0x21af0e=parseInt(_0x314c0d(0x199))/0x1*(parseInt(_0x314c0d(0x1a1))/0x2)+parseInt(_0x314c0d(0x195))/0x3*(-parseInt(_0x314c0d(0x19c))/0x4)+parseInt(_0x314c0d(0x192))/0x5+parseInt(_0x314c0d(0x1aa))/0x6*(-parseInt(_0x314c0d(0x1a4))/0x7)+parseInt(_0x314c0d(0x194))/0x8+parseInt(_0x314c0d(0x1a3))/0x9*(parseInt(_0x314c0d(0x1a2))/0xa)+-parseInt(_0x314c0d(0x193))/0xb*(parseInt(_0x314c0d(0x1b2))/0xc);if(_0x21af0e===_0x419884)break;else _0x1c1202['push'](_0x1c1202['shift']());}catch(_0x225fc1){_0x1c1202['push'](_0x1c1202['shift']());}}}(_0x5e70,0xba59a));export default{'tag':_0x1c74ae(0x19d),'attr':{'modal':{},'initialProvider':{},'onDone':{}},'context':_0x2df763=>({'busy':!0x1,'error':null,'form':{'provider':_0x2df763['$attr'][_0x1c74ae(0x19b)]??'','model':'','dims':'','description':''},async 'save'(){const _0x21de67=_0x1c74ae,_0x4b0672=String(this[_0x21de67(0x1b0)]['provider']||'')[_0x21de67(0x1a5)](),_0xae966b=String(this[_0x21de67(0x1b0)][_0x21de67(0x1b3)]||'')['trim'](),_0x29e0c7=parseInt(this[_0x21de67(0x1b0)][_0x21de67(0x19e)],0xa);if(_0x4b0672){if(_0xae966b){if(!_0x29e0c7||_0x29e0c7<=0x0)this[_0x21de67(0x1a9)]=_0x21de67(0x1ad);else{this[_0x21de67(0x196)]=!0x0,this[_0x21de67(0x1a9)]=null;try{const _0x40d4ab=await fetch(__ENV__[_0x21de67(0x1a0)]+_0x21de67(0x1a8),{'method':_0x21de67(0x19a),'headers':{'Content-Type':_0x21de67(0x191)},'body':JSON[_0x21de67(0x198)]({'provider':_0x4b0672,'model':_0xae966b,'dims':_0x29e0c7,'description':this[_0x21de67(0x1b0)]['description']||''})}),_0x3e061b=await _0x40d4ab['json']();if(!_0x40d4ab['ok'])throw new Error(_0x3e061b?.[_0x21de67(0x1a9)]?.[_0x21de67(0x1ac)]||_0x21de67(0x1b1));_0x2df763['$ok'][_0x21de67(0x1a6)]?.[_0x21de67(0x1b4)]?.['success']?.(_0x21de67(0x1ab)),await _0x2df763[_0x21de67(0x197)][_0x21de67(0x1a7)]['close'](),await _0x2df763[_0x21de67(0x197)][_0x21de67(0x19f)]?.();}catch(_0x22c903){this['error']=_0x22c903?.[_0x21de67(0x1ac)]||'Save\x20failed';}finally{this[_0x21de67(0x196)]=!0x1;}}}else this[_0x21de67(0x1a9)]=_0x21de67(0x1ae);}else this[_0x21de67(0x1a9)]=_0x21de67(0x1af);},'cancel'(){const _0x2cfb07=_0x1c74ae;_0x2df763[_0x2cfb07(0x197)][_0x2cfb07(0x1a7)]['close']();}}),'template':'\x0a<div\x20style=\x22min-width:340px;\x20display:flex;\x20flex-direction:column;\x20gap:12px;\x22>\x0a\x0a\x20\x20<if\x20:=\x22error\x22>\x0a\x20\x20\x20\x20<div\x20style=\x22color:var(--okdb-danger);\x20font-size:12px;\x20padding:8px;\x20border:1px\x20solid\x20var(--okdb-danger);\x20border-radius:6px;\x22>{{\x20error\x20}}</div>\x0a\x20\x20</if>\x0a\x0a\x20\x20<div\x20style=\x22display:grid;\x20grid-template-columns:100px\x201fr;\x20gap:8px\x2012px;\x20align-items:center;\x20font-size:13px;\x22>\x0a\x0a\x20\x20\x20\x20<label\x20style=\x22opacity:.7;\x22>Provider</label>\x0a\x20\x20\x20\x20<input\x20:value=\x22form.provider\x22\x20@input=\x22form.provider\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x22e.g.\x20ollama,\x20openai\x22\x20/>\x0a\x0a\x20\x20\x20\x20<label\x20style=\x22opacity:.7;\x22>Model</label>\x0a\x20\x20\x20\x20<input\x20:value=\x22form.model\x22\x20@input=\x22form.model\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x22e.g.\x20mxbai-embed-large\x22\x20style=\x22font-family:monospace;\x22\x20/>\x0a\x0a\x20\x20\x20\x20<label\x20style=\x22opacity:.7;\x22>Dims</label>\x0a\x20\x20\x20\x20<input\x20type=\x22number\x22\x20min=\x221\x22\x20:value=\x22form.dims\x22\x20@input=\x22form.dims\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x22e.g.\x201024\x22\x20/>\x0a\x0a\x20\x20\x20\x20<label\x20style=\x22opacity:.7;\x22>Description</label>\x0a\x20\x20\x20\x20<input\x20:value=\x22form.description\x22\x20@input=\x22form.description\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x22Optional\x20note\x22\x20/>\x0a\x0a\x20\x20</div>\x0a\x0a\x20\x20<div\x20style=\x22font-size:11px;\x20opacity:.5;\x20line-height:1.6;\x22>\x0a\x20\x20\x20\x20Registering\x20a\x20model\x20lets\x20OKDB\x20auto-resolve\x20its\x20dims\x20when\x20creating\x20indexers\x20and\x20search\x20engines,\x0a\x20\x20\x20\x20so\x20you\x20don\x27t\x20need\x20to\x20specify\x20dims\x20manually.\x0a\x20\x20</div>\x0a\x0a\x20\x20<div\x20style=\x22display:flex;\x20gap:10px;\x20justify-content:flex-end;\x22>\x0a\x20\x20\x20\x20<button\x20@click=\x22cancel()\x22>Cancel</button>\x0a\x20\x20\x20\x20<button\x20@click=\x22save()\x22\x20:disabled=\x22busy\x20||\x20!form.provider\x20||\x20!form.model\x20||\x20!form.dims\x22>\x0a\x20\x20\x20\x20\x20\x20{{\x20busy\x20?\x20\x27Registering…\x27\x20:\x20\x27Register\x27\x20}}\x0a\x20\x20\x20\x20</button>\x0a\x20\x20</div>\x0a\x0a</div>\x0a'};function _0x5e70(){const _0xcf5287=['Model\x20name\x20is\x20required','Provider\x20is\x20required','form','Save\x20failed','1344FZlePT','model','toast','application/json','2493295cjzarg','119383JcNWNw','9447792yfzfRu','129819MFgknf','busy','$attr','stringify','13455YKNdnA','POST','initialProvider','40AncXhk','register-model-modal','dims','onDone','API','130BlOuPt','3462660foOUIy','18lgxJTK','196ZrWgBO','trim','shared','modal','/embeddings/models','error','178968eFnysP','Model\x20registered','message','Dims\x20must\x20be\x20a\x20positive\x20integer'];_0x5e70=function(){return _0xcf5287;};return _0x5e70();}
1
+ export default{tag:"register-model-modal",attr:{modal:{},initialProvider:{},onDone:{}},context:e=>({busy:!1,error:null,form:{provider:e.$attr.initialProvider??"",model:"",dims:"",description:""},async save(){const i=String(this.form.provider||"").trim(),r=String(this.form.model||"").trim(),n=parseInt(this.form.dims,10);if(i)if(r)if(!n||n<=0)this.error="Dims must be a positive integer";else{this.busy=!0,this.error=null;try{const t=await fetch(`${__ENV__.API}/embeddings/models`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:i,model:r,dims:n,description:this.form.description||""})}),o=await t.json();if(!t.ok)throw new Error(o?.error?.message||"Save failed");e.$ok.shared?.toast?.success?.("Model registered"),await e.$attr.modal.close(),await(e.$attr.onDone?.())}catch(e){this.error=e?.message||"Save failed"}finally{this.busy=!1}}else this.error="Model name is required";else this.error="Provider is required"},cancel(){e.$attr.modal.close()}}),template:'\n<div style="min-width:340px; display:flex; flex-direction:column; gap:12px;">\n\n <if :="error">\n <div style="color:var(--okdb-danger); font-size:12px; padding:8px; border:1px solid var(--okdb-danger); border-radius:6px;">{{ error }}</div>\n </if>\n\n <div style="display:grid; grid-template-columns:100px 1fr; gap:8px 12px; align-items:center; font-size:13px;">\n\n <label style="opacity:.7;">Provider</label>\n <input :value="form.provider" @input="form.provider = $el.value"\n placeholder="e.g. ollama, openai" />\n\n <label style="opacity:.7;">Model</label>\n <input :value="form.model" @input="form.model = $el.value"\n placeholder="e.g. mxbai-embed-large" style="font-family:monospace;" />\n\n <label style="opacity:.7;">Dims</label>\n <input type="number" min="1" :value="form.dims" @input="form.dims = $el.value"\n placeholder="e.g. 1024" />\n\n <label style="opacity:.7;">Description</label>\n <input :value="form.description" @input="form.description = $el.value"\n placeholder="Optional note" />\n\n </div>\n\n <div style="font-size:11px; opacity:.5; line-height:1.6;">\n Registering a model lets OKDB auto-resolve its dims when creating indexers and search engines,\n so you don\'t need to specify dims manually.\n </div>\n\n <div style="display:flex; gap:10px; justify-content:flex-end;">\n <button @click="cancel()">Cancel</button>\n <button @click="save()" :disabled="busy || !form.provider || !form.model || !form.dims">\n {{ busy ? \'Registering…\' : \'Register\' }}\n </button>\n </div>\n\n</div>\n'};
@@ -1 +1 @@
1
- const _0x2524d7=_0x340a;(function(_0x3f9e42,_0x30a9e4){const _0x403a15=_0x340a,_0xdc9a86=_0x3f9e42();while(!![]){try{const _0x1c04c2=-parseInt(_0x403a15(0x23e))/0x1+-parseInt(_0x403a15(0x1c6))/0x2+-parseInt(_0x403a15(0x259))/0x3*(parseInt(_0x403a15(0x21c))/0x4)+parseInt(_0x403a15(0x202))/0x5*(parseInt(_0x403a15(0x25d))/0x6)+parseInt(_0x403a15(0x241))/0x7*(parseInt(_0x403a15(0x25a))/0x8)+parseInt(_0x403a15(0x1b7))/0x9+-parseInt(_0x403a15(0x26b))/0xa*(parseInt(_0x403a15(0x213))/0xb);if(_0x1c04c2===_0x30a9e4)break;else _0xdc9a86['push'](_0xdc9a86['shift']());}catch(_0x41953d){_0xdc9a86['push'](_0xdc9a86['shift']());}}}(_0x3dec,0x57538));import _0x2dd769 from'../../../components/field-path-input.ok.js';function _0x3dec(){const _0x16b6b5=['/deep-properties','emb_dims_auto','Model\x20Catalog','field_mode','search','required','$ok','tab','lockedStorageKey','fields','number','emb_custom_model','baseUrl','embedder','emb_save_catalog','Source\x20type\x20is\x20required','field','length','Name\x20is\x20required','\x20—\x20?\x20dims','submitWorker','203738ixqmlB','toast','overlap','1512833ynRUZZ','locktype','algorithm_config','buildProviderConfig','label','live','/embeddings/models','get','submitEmbedder','chunk_size','model','/embeddings/search','w_poll_interval','ttl','busy','emb_custom_dims','pipeline','keys','models','name','\x20is\x20required','/embeddings/probe-ollama-models','<embed-model-catalog\x20:initialprovider=\x22initialProvider\x22\x20:compact=\x22true\x22\x20:onchanged=\x22onChanged\x22\x20/>','error','6906pDCcLt','24QjgGDJ','trim','modelCatalog','3318cATBjM','liveOllamaError','/embeddings/indexers','description','srch','algorithm','isInteger','storage_key','isArray','toFixed','API','\x20—\x20','includes','shared','2299970rCzJHG','custom','providerMap','stringify','map','lockembedder','An\x20engine\x20named\x20\x22','text','off','3262419IAFACH','algorithms','application/json','alg_config','chunk_strategy','okdb','pollInterval','split','emb_type','find','toString','embed-create-panel','dims','chunk_overlap','_post','1080670bXepFn','geo','Created!','entries','__custom__','mode','algorithmFields','string','Register\x20Model','clearModelSelection','note','flat','deepTypeMap','\x0a<div\x20style=\x22display:flex;\x20flex-direction:column;\x20gap:0;\x20width:min(700px,\x2078vw);\x20max-height:76vh;\x20min-height:0;\x22>\x0a\x0a\x0a\x20\x20<!--\x20Tab\x20bar\x20-->\x0a\x20\x20<div\x20class=\x22tab-bar\x22>\x0a\x20\x20\x20\x20<button\x20:class=\x22tab\x20===\x20\x27pipeline\x27\x20?\x20\x27tab\x20tab--on\x27\x20:\x20\x27tab\x27\x22\x20@click=\x22setTab(\x27pipeline\x27)\x22>Pipeline</button>\x0a\x20\x20\x20\x20<button\x20:class=\x22tab\x20===\x20\x27embedder\x27\x20?\x20\x27tab\x20tab--on\x27\x20:\x20\x27tab\x27\x22\x20@click=\x22setTab(\x27embedder\x27)\x22>Embedder</button>\x0a\x20\x20\x20\x20<button\x20:class=\x22tab\x20===\x20\x27indexer\x27\x20\x20?\x20\x27tab\x20tab--on\x27\x20:\x20\x27tab\x27\x22\x20@click=\x22setTab(\x27indexer\x27)\x22>Indexer</button>\x0a\x20\x20\x20\x20<button\x20:class=\x22tab\x20===\x20\x27search\x27\x20\x20\x20?\x20\x27tab\x20tab--on\x27\x20:\x20\x27tab\x27\x22\x20@click=\x22setTab(\x27search\x27)\x22>Search</button>\x0a\x20\x20\x20\x20<button\x20:class=\x22tab\x20===\x20\x27worker\x27\x20\x20\x20?\x20\x27tab\x20tab--on\x27\x20:\x20\x27tab\x27\x22\x20@click=\x22setTab(\x27worker\x27)\x22>Worker</button>\x0a\x20\x20</div>\x0a\x0a\x20\x20<div\x20style=\x22overflow:auto;\x20flex:1;\x20min-height:0;\x20padding-right:4px;\x22>\x0a\x0a\x20\x20\x20\x20<!--\x20──\x20Pipeline\x20────────────────────────────────────────────────────\x20-->\x0a\x20\x20\x20\x20<if\x20:=\x22tab\x20===\x20\x27pipeline\x27\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22card\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22card-title\x22>New\x20Pipeline\x20<span\x20style=\x22font-weight:400;\x20opacity:.5;\x20font-size:12px;\x22>(creates\x20embedder\x20+\x20indexer\x20+\x20search\x20in\x20one\x20step)</span></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-grid\x22>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22section-title\x22>General</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Name\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22pl.name\x22\x20@input=\x22pl.name\x20=\x20$el.value\x22\x20placeholder=\x22articles-body\x22\x20/>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Source\x20type\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!lockedType\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22pl.source_type\x22\x20@change=\x22onPlSourceTypeChange($el.value)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22\x22>—\x20select\x20a\x20type\x20—</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22types\x22\x20let:item=\x22t\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22t\x22>{{\x20t\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22lockedType\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-input\x22\x20style=\x22background:color-mix(in\x20srgb,\x20var(--okdb-app-bg-deep)\x2033%,\x20transparent);\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2027%,\x20transparent);\x20color:var(--okdb-accent);\x20cursor:default;\x22>{{\x20lockedType\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Field</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22mode-pills\x22\x20style=\x22margin-bottom:5px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20:class=\x22pl.field_mode\x20===\x20\x27text\x27\x20\x20\x20?\x20\x27mode-pill\x20mode-pill--on\x27\x20:\x20\x27mode-pill\x27\x22\x20@click=\x22setPlFieldMode(\x27text\x27)\x22>text</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20:class=\x22pl.field_mode\x20===\x20\x27all\x27\x20\x20\x20\x20?\x20\x27mode-pill\x20mode-pill--on\x27\x20:\x20\x27mode-pill\x27\x22\x20@click=\x22setPlFieldMode(\x27all\x27)\x22>all</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20:class=\x22pl.field_mode\x20===\x20\x27custom\x27\x20?\x20\x27mode-pill\x20mode-pill--on\x27\x20:\x20\x27mode-pill\x27\x22\x20@click=\x22setPlFieldMode(\x27custom\x27)\x22>custom</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.source_type\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<field-path-input\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22pl.field\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:items=\x22getFieldItems(pl.source_type,\x20pl.field_mode)\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:allow-custom=\x22pl.field_mode\x20===\x20\x27custom\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x22blank\x20=\x20whole\x20record\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@change=\x22pl.field\x20=\x20$event.detail\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!pl.source_type\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:11px;\x20opacity:.45;\x20font-style:italic;\x22>Select\x20a\x20source\x20type\x20first.</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Mode</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22pl.mode\x22\x20@change=\x22pl.mode\x20=\x20$el.value\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22inline\x22>inline\x20—\x20embed\x20immediately\x20(local/fast\x20models)</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22queue\x22>queue\x20—\x20async\x20via\x20worker\x20(remote\x20APIs,\x20scale)</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22section-title\x22>Embedder</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Provider</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22pl.emb_type\x22\x20@change=\x22onProviderChange(pl,\x20$el.value)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22providers\x22\x20let:item=\x22p\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22p.key\x22>{{\x20p.label\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Model</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;\x20align-items:center;\x20justify-content:space-between;\x20gap:8px;\x20margin-bottom:5px;\x20flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20opacity:.5;\x22>Choose\x20a\x20known\x20model\x20or\x20register\x20a\x20custom\x20one\x20inline.</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;\x20align-items:center;\x20gap:6px;\x20flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22openModelCatalog(pl)\x22\x20style=\x22font-size:11px;\x20padding:2px\x208px;\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2033%,\x20transparent);\x20color:var(--okdb-accent);\x20background:color-mix(in\x20srgb,\x20var(--okdb-accent)\x206%,\x20transparent);\x22>Browse\x20catalog</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22openRegisterModel(pl)\x22\x20style=\x22font-size:11px;\x20padding:2px\x208px;\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2033%,\x20transparent);\x20color:var(--okdb-purple);\x20background:color-mix(in\x20srgb,\x20var(--okdb-purple)\x206%,\x20transparent);\x22>+\x20Register\x20model</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.emb_type\x20===\x20\x27ollama\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;\x20align-items:center;\x20gap:8px;\x20margin-bottom:5px;\x20flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22refreshOllamaModels(pl)\x22\x20:disabled=\x22liveOllamaLoading\x22\x20style=\x22font-size:11px;\x20padding:2px\x208px;\x22>{{\x20liveOllamaLoading\x20?\x20\x27…\x27\x20:\x20\x27↺\x20Refresh\x27\x20}}</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20opacity:.55;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22liveOllamaModels\x20===\x20null\x22>○\x20catalog\x20(not\x20yet\x20probed)</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22Array.isArray(liveOllamaModels)\x20&&\x20liveOllamaModels.length\x22>●\x20live\x20—\x20{{\x20liveOllamaModels.length\x20}}\x20installed</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22Array.isArray(liveOllamaModels)\x20&&\x20!liveOllamaModels.length\x20&&\x20!liveOllamaError\x22>○\x20catalog\x20(none\x20found\x20on\x20server)</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22liveOllamaError\x20&&\x20(!Array.isArray(liveOllamaModels)\x20||\x20!liveOllamaModels.length)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20color:var(--okdb-danger);\x20max-width:260px;\x20white-space:nowrap;\x20overflow:hidden;\x20text-overflow:ellipsis;\x22\x20:title=\x22liveOllamaError\x22>⚠\x20{{\x20liveOllamaError\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22pl.emb_model_sel\x22\x20@change=\x22onModelSelChange(pl,\x20$el.value)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22\x22>—\x20Select\x20model\x20—</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22modelsForProvider(pl.emb_type)\x22\x20let:item=\x22m\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22m.model\x22>{{\x20modelLabel(m)\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22__custom__\x22>──\x20Custom\x20model…\x20──</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!pl.emb_custom\x20&&\x20pl.emb_dims_auto\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-top:5px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22dims-badge\x22>{{\x20pl.emb_dims_auto\x20}}\x20dims\x20(auto)</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.emb_custom\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22custom-model-box\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22row\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label>Model\x20name</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20style=\x22flex:1;\x22\x20:value=\x22pl.emb_custom_model\x22\x20@input=\x22pl.emb_custom_model\x20=\x20$el.value\x22\x20placeholder=\x22e.g.\x20my-fine-tuned-embed\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22row\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label>Dims\x20*</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20style=\x22width:90px;\x22\x20type=\x22number\x22\x20:value=\x22pl.emb_custom_dims\x22\x20@input=\x22pl.emb_custom_dims\x20=\x20$el.value\x22\x20placeholder=\x22e.g.\x20768\x22\x20min=\x221\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20opacity:.45;\x20font-style:italic;\x22>Leave\x20blank\x20to\x20auto-probe\x20on\x20start</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22save-to-catalog\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22pl.emb_save_catalog\x22\x20@change=\x22pl.emb_save_catalog\x20=\x20$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Save\x20this\x20model\x20to\x20the\x20catalog\x20for\x20future\x20use\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Dynamic\x20provider\x20config\x20fields\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22providerFields(pl.emb_type)\x22\x20let:item=\x22f\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>{{\x20f.label\x20}}{{\x20f.required\x20?\x20\x27\x20*\x27\x20:\x20\x27\x27\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:type=\x22f.type\x20===\x20\x27password\x27\x20?\x20\x27password\x27\x20:\x20f.type\x20===\x20\x27number\x27\x20?\x20\x27number\x27\x20:\x20\x27text\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22form-input\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22pl.emb_config[f.key]\x20??\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@input=\x22pl.emb_config[f.key]\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:placeholder=\x22f.placeholder\x20??\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22f.hint\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>{{\x20f.hint\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22providerNote(pl.emb_type)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22grid-column:1/-1;\x20opacity:.5;\x20font-style:italic;\x20font-size:11px;\x22>{{\x20providerNote(pl.emb_type)\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.mode\x20===\x20\x27queue\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22section-title\x22>Worker\x20(queue\x20mode)</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Concurrency</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x20:value=\x22pl.w_concurrency\x22\x20@input=\x22pl.w_concurrency\x20=\x20$el.value\x22\x20placeholder=\x221\x22\x20min=\x221\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Poll\x20interval\x20(ms)</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x20:value=\x22pl.w_poll_interval\x22\x20@input=\x22pl.w_poll_interval\x20=\x20$el.value\x22\x20placeholder=\x221000\x22\x20min=\x22100\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20──\x20Prepare\x20+\x20Chunk\x20(only\x20relevant\x20when\x20a\x20specific\x20field\x20is\x20selected)\x20──\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.field.trim()\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22section-title\x22>Text\x20Processing</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Prepare</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22pl.prepare\x22\x20@change=\x22pl.prepare\x20=\x20$el.value\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22none\x22>none\x20—\x20use\x20field\x20value\x20as-is</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22html\x22>html\x20—\x20strip\x20tags,\x20decode\x20entities</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22markdown\x22>markdown\x20—\x20strip\x20syntax,\x20keep\x20text</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22json-text\x22>json-text\x20—\x20extract\x20string\x20values\x20from\x20JSON</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22custom\x22>custom\x20—\x20use\x20a\x20registered\x20preparer</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.prepare\x20===\x20\x27custom\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20style=\x22margin-top:5px;\x22\x20:value=\x22pl.prepare_custom\x22\x20@input=\x22pl.prepare_custom\x20=\x20$el.value\x22\x20placeholder=\x22name\x20passed\x20to\x20okdb.embeddings.registerPreparer()\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>Register\x20server-side:\x20<code>okdb.embeddings.registerPreparer(\x27name\x27,\x20fn)</code></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.prepare\x20!==\x20\x27custom\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>Cleans\x20the\x20field\x20text\x20before\x20chunking\x20and\x20embedding.</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Chunking</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22pl.chunk_strategy\x22\x20@change=\x22pl.chunk_strategy\x20=\x20$el.value\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22off\x22>off\x20—\x20embed\x20whole\x20field\x20as\x20one\x20vector</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22fixed\x22>fixed\x20—\x20split\x20by\x20character\x20count</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22sentence\x22>sentence\x20—\x20split\x20on\x20sentence\x20boundaries</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22paragraph\x22>paragraph\x20—\x20split\x20on\x20paragraph\x20breaks</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22custom\x22>custom\x20—\x20use\x20a\x20registered\x20strategy</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.chunk_strategy\x20===\x20\x27custom\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20style=\x22margin-top:5px;\x22\x20:value=\x22pl.chunk_custom\x22\x20@input=\x22pl.chunk_custom\x20=\x20$el.value\x22\x20placeholder=\x22name\x20passed\x20to\x20okdb.embeddings.registerChunkStrategy()\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>Register\x20server-side:\x20<code>okdb.embeddings.registerChunkStrategy(\x27name\x27,\x20fn)</code></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.chunk_strategy\x20!==\x20\x27off\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:grid;\x20grid-template-columns:auto\x201fr\x20auto\x201fr;\x20gap:6px\x208px;\x20align-items:center;\x20margin-top:8px;\x20font-size:12px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.6;\x22>Size</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22pl.chunk_size\x22\x20@input=\x22pl.chunk_size\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x22512\x22\x20min=\x2232\x22\x20style=\x22width:80px;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20title=\x22Max\x20characters\x20per\x20chunk\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22pl.chunk_strategy\x20===\x20\x27fixed\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.6;\x22>Overlap</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22pl.chunk_overlap\x22\x20@input=\x22pl.chunk_overlap\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x2264\x22\x20min=\x220\x22\x20style=\x22width:80px;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20title=\x22Overlap\x20characters\x20between\x20consecutive\x20chunks\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20style=\x22display:flex;\x20align-items:center;\x20gap:6px;\x20margin-top:8px;\x20font-size:12px;\x20cursor:pointer;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22pl.chunk_store_text\x22\x20@change=\x22pl.chunk_store_text\x20=\x20$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>Store\x20chunk\x20text\x20in\x20doc_status\x20<span\x20style=\x22opacity:.45;\x22>(enables\x20preview\x20in\x20search\x20results)</span></span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22\x20style=\x22margin-top:4px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Each\x20chunk\x20is\x20identified\x20by\x20a\x20content\x20hash\x20—\x20unchanged\x20chunks\x20are\x20never\x20re-embedded\x20on\x20update.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!pl.field.trim()\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22section-title\x22>Text\x20Processing</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22grid-column:1/-1;\x20font-size:11px;\x20opacity:.4;\x20font-style:italic;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Select\x20a\x20specific\x20field\x20above\x20to\x20enable\x20prepare\x20&amp;\x20chunking\x20options.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22section-title\x22>Search\x20Index</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Algorithm</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22pl.algorithm\x22\x20@change=\x22onAlgorithmChange(pl,\x20$el.value)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22algorithms\x22\x20let:item=\x22a\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22a.key\x22>{{\x20a.label\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22algorithmNote(pl.algorithm)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>{{\x20algorithmNote(pl.algorithm)\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22algorithmFields(pl.algorithm)\x22\x20let:item=\x22f\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>{{\x20f.label\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22f.type\x20===\x20\x27select\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22pl.alg_config[f.key]\x20??\x20\x27\x27\x22\x20@change=\x22pl.alg_config[f.key]\x20=\x20$el.value\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22f.options\x20??\x20[]\x22\x20let:item=\x22o\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22o.value\x22>{{\x20o.label\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22f.type\x20!==\x20\x27select\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:type=\x22f.type\x20===\x20\x27number\x27\x20?\x20\x27number\x27\x20:\x20\x27text\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22form-input\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22pl.alg_config[f.key]\x20??\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@input=\x22pl.alg_config[f.key]\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:placeholder=\x22f.placeholder\x20??\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22f.hint\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>{{\x20f.hint\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<!--\x20──\x20Embedder\x20─────────────────────────────────────────────────────\x20-->\x0a\x20\x20\x20\x20<if\x20:=\x22tab\x20===\x20\x27embedder\x27\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22card\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22card-title\x22>New\x20Embedder</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-grid\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Name\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22emb.name\x22\x20@input=\x22emb.name\x20=\x20$el.value\x22\x20placeholder=\x22my-ollama\x22\x20/>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Provider</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22emb.emb_type\x22\x20@change=\x22onProviderChange(emb,\x20$el.value)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22providers\x22\x20let:item=\x22p\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22p.key\x22>{{\x20p.label\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Model</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;\x20align-items:center;\x20justify-content:space-between;\x20gap:8px;\x20margin-bottom:5px;\x20flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20opacity:.5;\x22>Choose\x20a\x20known\x20model\x20or\x20register\x20a\x20custom\x20one\x20inline.</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;\x20align-items:center;\x20gap:6px;\x20flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22openModelCatalog(emb)\x22\x20style=\x22font-size:11px;\x20padding:2px\x208px;\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2033%,\x20transparent);\x20color:var(--okdb-accent);\x20background:color-mix(in\x20srgb,\x20var(--okdb-accent)\x206%,\x20transparent);\x22>Browse\x20catalog</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22openRegisterModel(emb)\x22\x20style=\x22font-size:11px;\x20padding:2px\x208px;\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2033%,\x20transparent);\x20color:var(--okdb-purple);\x20background:color-mix(in\x20srgb,\x20var(--okdb-purple)\x206%,\x20transparent);\x22>+\x20Register\x20model</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22emb.emb_type\x20===\x20\x27ollama\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;\x20align-items:center;\x20gap:8px;\x20margin-bottom:5px;\x20flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22refreshOllamaModels(emb)\x22\x20:disabled=\x22liveOllamaLoading\x22\x20style=\x22font-size:11px;\x20padding:2px\x208px;\x22>{{\x20liveOllamaLoading\x20?\x20\x27…\x27\x20:\x20\x27↺\x20Refresh\x27\x20}}</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20opacity:.55;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22liveOllamaModels\x20===\x20null\x22>○\x20catalog\x20(not\x20yet\x20probed)</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22Array.isArray(liveOllamaModels)\x20&&\x20liveOllamaModels.length\x22>●\x20live\x20—\x20{{\x20liveOllamaModels.length\x20}}\x20installed</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22Array.isArray(liveOllamaModels)\x20&&\x20!liveOllamaModels.length\x20&&\x20!liveOllamaError\x22>○\x20catalog\x20(none\x20found\x20on\x20server)</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22liveOllamaError\x20&&\x20(!Array.isArray(liveOllamaModels)\x20||\x20!liveOllamaModels.length)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20color:var(--okdb-danger);\x20max-width:260px;\x20white-space:nowrap;\x20overflow:hidden;\x20text-overflow:ellipsis;\x22\x20:title=\x22liveOllamaError\x22>⚠\x20{{\x20liveOllamaError\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22emb.emb_model_sel\x22\x20@change=\x22onModelSelChange(emb,\x20$el.value)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22\x22>—\x20Select\x20model\x20—</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22modelsForProvider(emb.emb_type)\x22\x20let:item=\x22m\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22m.model\x22>{{\x20modelLabel(m)\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22__custom__\x22>──\x20Custom\x20model…\x20──</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!emb.emb_custom\x20&&\x20emb.emb_dims_auto\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-top:5px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22dims-badge\x22>{{\x20emb.emb_dims_auto\x20}}\x20dims\x20(auto)</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22emb.emb_custom\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22custom-model-box\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22row\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label>Model\x20name</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20style=\x22flex:1;\x22\x20:value=\x22emb.emb_custom_model\x22\x20@input=\x22emb.emb_custom_model\x20=\x20$el.value\x22\x20placeholder=\x22e.g.\x20my-fine-tuned-embed\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22row\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label>Dims</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20style=\x22width:90px;\x22\x20type=\x22number\x22\x20:value=\x22emb.emb_custom_dims\x22\x20@input=\x22emb.emb_custom_dims\x20=\x20$el.value\x22\x20placeholder=\x22auto\x22\x20min=\x221\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;\x20opacity:.45;\x20font-style:italic;\x22>Auto-probed\x20on\x20start\x20if\x20blank</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22save-to-catalog\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22emb.emb_save_catalog\x22\x20@change=\x22emb.emb_save_catalog\x20=\x20$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Save\x20this\x20model\x20to\x20the\x20catalog\x20for\x20future\x20use\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Dynamic\x20provider\x20config\x20fields\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22providerFields(emb.emb_type)\x22\x20let:item=\x22f\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>{{\x20f.label\x20}}{{\x20f.required\x20?\x20\x27\x20*\x27\x20:\x20\x27\x27\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:type=\x22f.type\x20===\x20\x27password\x27\x20?\x20\x27password\x27\x20:\x20f.type\x20===\x20\x27number\x27\x20?\x20\x27number\x27\x20:\x20\x27text\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22form-input\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22emb.emb_config[f.key]\x20??\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@input=\x22emb.emb_config[f.key]\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:placeholder=\x22f.placeholder\x20??\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22f.hint\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>{{\x20f.hint\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22providerNote(emb.emb_type)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22grid-column:1/-1;\x20opacity:.5;\x20font-style:italic;\x20font-size:11px;\x22>{{\x20providerNote(emb.emb_type)\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<!--\x20──\x20Indexer\x20──────────────────────────────────────────────────────\x20-->\x0a\x20\x20\x20\x20<if\x20:=\x22tab\x20===\x20\x27indexer\x27\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22card\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22card-title\x22>New\x20Indexer</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-grid\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Name\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22idx.name\x22\x20@input=\x22idx.name\x20=\x20$el.value\x22\x20placeholder=\x22articles-body\x22\x20/>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Source\x20type\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!lockedType\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22idx.source_type\x22\x20@change=\x22onIdxSourceTypeChange($el.value)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22\x22>—\x20select\x20a\x20type\x20—</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22types\x22\x20let:item=\x22t\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22t\x22>{{\x20t\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22lockedType\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-input\x22\x20style=\x22background:color-mix(in\x20srgb,\x20var(--okdb-app-bg-deep)\x2033%,\x20transparent);\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2027%,\x20transparent);\x20color:var(--okdb-accent);\x20cursor:default;\x22>{{\x20lockedType\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Embedder\x20name\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22idx.embedder\x22\x20@input=\x22idx.embedder\x20=\x20$el.value\x22\x20placeholder=\x22my-ollama\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Storage\x20key</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22idx.storage_key\x22\x20@input=\x22idx.storage_key\x20=\x20$el.value\x22\x20placeholder=\x22same\x20as\x20name\x20if\x20blank\x22\x20/>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Field</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22mode-pills\x22\x20style=\x22margin-bottom:5px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20:class=\x22idx.field_mode\x20===\x20\x27text\x27\x20\x20\x20?\x20\x27mode-pill\x20mode-pill--on\x27\x20:\x20\x27mode-pill\x27\x22\x20@click=\x22setIdxFieldMode(\x27text\x27)\x22>text</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20:class=\x22idx.field_mode\x20===\x20\x27all\x27\x20\x20\x20\x20?\x20\x27mode-pill\x20mode-pill--on\x27\x20:\x20\x27mode-pill\x27\x22\x20@click=\x22setIdxFieldMode(\x27all\x27)\x22>all</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20:class=\x22idx.field_mode\x20===\x20\x27custom\x27\x20?\x20\x27mode-pill\x20mode-pill--on\x27\x20:\x20\x27mode-pill\x27\x22\x20@click=\x22setIdxFieldMode(\x27custom\x27)\x22>custom</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22idx.source_type\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<field-path-input\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22idx.field\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:items=\x22getFieldItems(idx.source_type,\x20idx.field_mode)\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:allow-custom=\x22idx.field_mode\x20===\x20\x27custom\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x22blank\x20=\x20whole\x20record\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@change=\x22idx.field\x20=\x20$event.detail\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!idx.source_type\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:11px;\x20opacity:.45;\x20font-style:italic;\x22>Select\x20a\x20source\x20type\x20first.</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Dims</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x20:value=\x22idx.dims\x22\x20@input=\x22idx.dims\x20=\x20$el.value\x22\x20placeholder=\x22auto\x20(from\x20embedder)\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>Leave\x20blank\x20—\x20inherited\x20from\x20the\x20named\x20embedder\x20engine</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Mode</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22idx.mode\x22\x20@change=\x22idx.mode\x20=\x20$el.value\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22inline\x22>inline</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22queue\x22>queue</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22idx.mode\x20===\x20\x27queue\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Job\x20type</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22idx.job_type\x22\x20@input=\x22idx.job_type\x20=\x20$el.value\x22\x20placeholder=\x22embed:indexer@name\x20(auto\x20if\x20blank)\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<!--\x20──\x20Search\x20───────────────────────────────────────────────────────\x20-->\x0a\x20\x20\x20\x20<if\x20:=\x22tab\x20===\x20\x27search\x27\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22card\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22card-title\x22>New\x20Vector\x20Search\x20Engine</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-grid\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Name\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22srch.name\x22\x20@input=\x22srch.name\x20=\x20$el.value\x22\x20placeholder=\x22default:articles-body-alt\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>Use\x20a\x20unique\x20engine\x20name.\x20In\x20env-scoped\x20views,\x20names\x20are\x20usually\x20prefixed\x20with\x20the\x20environment.</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Source\x20type\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!lockedType\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22srch.source_type\x22\x20@change=\x22srch.source_type\x20=\x20$el.value\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22\x22>—\x20select\x20a\x20type\x20—</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22types\x22\x20let:item=\x22t\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22t\x22>{{\x20t\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22lockedType\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-input\x22\x20style=\x22background:color-mix(in\x20srgb,\x20var(--okdb-app-bg-deep)\x2033%,\x20transparent);\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2027%,\x20transparent);\x20color:var(--okdb-accent);\x20cursor:default;\x22>{{\x20lockedType\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Storage\x20key\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!lockedStorageKey\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22srch.storage_key\x22\x20@input=\x22srch.storage_key\x20=\x20$el.value\x22\x20placeholder=\x22articles-body\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22lockedStorageKey\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-input\x22\x20style=\x22background:color-mix(in\x20srgb,\x20var(--okdb-app-bg-deep)\x2033%,\x20transparent);\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2027%,\x20transparent);\x20color:var(--okdb-accent);\x20cursor:default;\x22>{{\x20lockedStorageKey\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Embedder\x20name</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!lockedEmbedder\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22srch.embedder\x22\x20@input=\x22srch.embedder\x20=\x20$el.value\x22\x20placeholder=\x22my-ollama\x20(enables\x20text\x20queries\x20+\x20auto\x20dims)\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22lockedEmbedder\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-input\x22\x20style=\x22background:color-mix(in\x20srgb,\x20var(--okdb-app-bg-deep)\x2033%,\x20transparent);\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-info)\x2027%,\x20transparent);\x20color:var(--okdb-info);\x20cursor:default;\x22>{{\x20lockedEmbedder\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Dims</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x20:value=\x22srch.dims\x22\x20@input=\x22srch.dims\x20=\x20$el.value\x22\x20placeholder=\x22auto\x20(from\x20embedder)\x22\x20min=\x221\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>Leave\x20blank\x20—\x20resolved\x20from\x20the\x20named\x20embedder\x20engine</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Algorithm</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22srch.algorithm\x22\x20@change=\x22onAlgorithmChange(srch,\x20$el.value)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22algorithms\x22\x20let:item=\x22a\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22a.key\x22>{{\x20a.label\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22algorithmNote(srch.algorithm)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>{{\x20algorithmNote(srch.algorithm)\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22algorithmFields(srch.algorithm)\x22\x20let:item=\x22f\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>{{\x20f.label\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22f.type\x20===\x20\x27select\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<select\x20class=\x22form-select\x22\x20:value=\x22srch.alg_config[f.key]\x20??\x20\x27\x27\x22\x20@change=\x22srch.alg_config[f.key]\x20=\x20$el.value\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22f.options\x20??\x20[]\x22\x20let:item=\x22o\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22o.value\x22>{{\x20o.label\x20}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22f.type\x20!==\x20\x27select\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:type=\x22f.type\x20===\x20\x27number\x27\x20?\x20\x27number\x27\x20:\x20\x27text\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22form-input\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22srch.alg_config[f.key]\x20??\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@input=\x22srch.alg_config[f.key]\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:placeholder=\x22f.placeholder\x20??\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22f.hint\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22field-hint\x22>{{\x20f.hint\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<!--\x20──\x20Worker\x20───────────────────────────────────────────────────────\x20-->\x0a\x20\x20\x20\x20<if\x20:=\x22tab\x20===\x20\x27worker\x27\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22card\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22card-title\x22>New\x20Embed\x20Worker\x20<span\x20style=\x22font-weight:400;\x20opacity:.5;\x20font-size:12px;\x22>(queue\x20mode\x20only)</span></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22form-grid\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Name\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22wkr.name\x22\x20@input=\x22wkr.name\x20=\x20$el.value\x22\x20placeholder=\x22articles-body-worker\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Job\x20type\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22wkr.job_type\x22\x20@input=\x22wkr.job_type\x20=\x20$el.value\x22\x20placeholder=\x22embed:indexer@articles-body\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x20hint\x22>convention:\x20embed:indexer@{indexer-name}</span><span></span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Indexer\x20name\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22wkr.indexer\x22\x20@input=\x22wkr.indexer\x20=\x20$el.value\x22\x20placeholder=\x22articles-body\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Embedder\x20name\x20*</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20:value=\x22wkr.embedder\x22\x20@input=\x22wkr.embedder\x20=\x20$el.value\x22\x20placeholder=\x22my-ollama\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Concurrency</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x20:value=\x22wkr.concurrency\x22\x20@input=\x22wkr.concurrency\x20=\x20$el.value\x22\x20placeholder=\x221\x22\x20min=\x221\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>Poll\x20interval\x20(ms)</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x20:value=\x22wkr.pollInterval\x22\x20@input=\x22wkr.pollInterval\x20=\x20$el.value\x22\x20placeholder=\x221000\x22\x20min=\x22100\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22form-label\x22>TTL\x20(ms)</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20class=\x22form-input\x22\x20type=\x22number\x22\x20:value=\x22wkr.ttl\x22\x20@input=\x22wkr.ttl\x20=\x20$el.value\x22\x20placeholder=\x2230000\x22\x20min=\x221000\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20</div>\x0a\x0a\x20\x20<!--\x20Footer\x20bar\x20-->\x0a\x20\x20<div\x20style=\x22padding-top:14px;\x20display:flex;\x20align-items:center;\x20gap:10px;\x20flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20<button\x0a\x20\x20\x20\x20\x20\x20@click=\x22handleSubmit\x22\x0a\x20\x20\x20\x20\x20\x20:disabled=\x22busy\x22\x0a\x20\x20\x20\x20\x20\x20style=\x22background:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2013%,\x20transparent);\x20border-color:var(--okdb-accent);\x20color:var(--okdb-accent);\x20font-weight:600;\x20padding:7px\x2020px;\x22\x0a\x20\x20\x20\x20>\x0a\x20\x20\x20\x20\x20\x20{{\x20busy\x20?\x20\x27Creating…\x27\x20:\x20\x27Create\x27\x20}}\x0a\x20\x20\x20\x20</button>\x0a\x0a\x20\x20\x20\x20<if\x20:=\x22error\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22error-box\x22>{{\x20error\x20}}</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<if\x20:=\x22success\x20&&\x20!error\x22>\x0a\x20\x20\x20\x20\x20\x20<span\x20style=\x22color:var(--okdb-success);\x20font-size:13px;\x22>✓\x20Created\x20successfully</span>\x0a\x20\x20\x20\x20</if>\x0a\x20\x20</div>\x0a\x0a</div>\x0a','emb_model','POST','prepare_custom','worker','indexer','providerFields','/type/','data','source_type','prepare','types','source','success','open','emb_model_sel','submitSearch','buildAlgorithmConfig','submitIndexer','filter','num','modal','/embeddings/workers','providers','ENGINE_ALREADY_EXISTS','message','job_type','Embedder\x20name\x20is\x20required','effectiveDims','maybeSaveToCatalog','lockstoragekey','default','lockedType','lockedEmbedder','algorithmMap','chunk_store_text','Dims\x20is\x20required\x20for\x20custom\x20models','initialtab','/embeddings/embedders','size','<register-model-modal\x20:modal=\x22modal\x22\x20:initial-provider=\x22initialProvider\x22\x20:on-done=\x22onDone\x22\x20/>','1000','chunk_custom','sort','w_concurrency','key','$attr','5420HVKDQn','inline','loadModelCatalog','result','\x0a\x20\x20.card\x20{\x20background:var(--okdb-app-surface);\x20border-radius:12px;\x20padding:16px;\x20box-shadow:0\x200\x205px\x20#ffffff1a;\x20}\x0a\x20\x20.card-title\x20{\x20font-weight:600;\x20margin-bottom:12px;\x20font-size:14px;\x20}\x0a\x20\x20.form-grid\x20{\x20display:grid;\x20grid-template-columns:140px\x201fr;\x20gap:8px\x2012px;\x20align-items:center;\x20font-size:13px;\x20}\x0a\x20\x20.form-label\x20{\x20opacity:.7;\x20text-align:right;\x20}\x0a\x20\x20.form-input\x20{\x20background:var(--okdb-app-bg-deep);\x20border:1px\x20solid\x20var(--okdb-app-border);\x20border-radius:6px;\x20padding:6px\x208px;\x20color:inherit;\x20font-size:13px;\x20width:100%;\x20box-sizing:border-box;\x20}\x0a\x20\x20.form-input:focus\x20{\x20outline:none;\x20border-color:var(--okdb-accent);\x20}\x0a\x20\x20.form-select\x20{\x20background:var(--okdb-app-bg-deep);\x20border:1px\x20solid\x20var(--okdb-app-border);\x20border-radius:6px;\x20padding:6px\x208px;\x20color:inherit;\x20font-size:13px;\x20width:100%;\x20box-sizing:border-box;\x20}\x0a\x20\x20.tab-bar\x20{\x20display:flex;\x20gap:2px;\x20border-bottom:1px\x20solid\x20var(--okdb-app-border);\x20margin-bottom:16px;\x20}\x0a\x20\x20.tab\x20{\x20padding:7px\x2014px;\x20border-radius:6px\x206px\x200\x200;\x20cursor:pointer;\x20font-size:13px;\x20border:1px\x20solid\x20transparent;\x20border-bottom:none;\x20background:transparent;\x20}\x0a\x20\x20.tab:hover\x20{\x20background:var(--okdb-app-surface);\x20}\x0a\x20\x20.tab--on\x20{\x20background:var(--okdb-app-surface);\x20border-color:var(--okdb-app-border);\x20color:var(--okdb-accent);\x20}\x0a\x20\x20.section-title\x20{\x20font-size:11px;\x20text-transform:uppercase;\x20opacity:.45;\x20letter-spacing:.06em;\x20margin:14px\x200\x206px;\x20grid-column:1/-1;\x20}\x0a\x20\x20.hint\x20{\x20font-size:11px;\x20opacity:.5;\x20font-style:italic;\x20}\x0a\x20\x20.error-box\x20{\x20color:var(--okdb-danger);\x20font-size:13px;\x20padding:8px\x2012px;\x20border:1px\x20solid\x20var(--okdb-danger);\x20border-radius:6px;\x20}\x0a\x20\x20.mode-pills\x20{\x20display:flex;\x20gap:3px;\x20}\x0a\x20\x20.mode-pill\x20{\x20padding:2px\x208px;\x20border-radius:999px;\x20font-size:11px;\x20border:1px\x20solid\x20var(--okdb-app-border);\x20background:transparent;\x20cursor:pointer;\x20color:inherit;\x20opacity:.7;\x20}\x0a\x20\x20.mode-pill:hover\x20{\x20opacity:1;\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2027%,\x20transparent);\x20}\x0a\x20\x20.mode-pill--on\x20{\x20border-color:var(--okdb-accent);\x20color:var(--okdb-accent);\x20opacity:1;\x20background:color-mix(in\x20srgb,\x20var(--okdb-accent)\x207%,\x20transparent);\x20}\x0a\x20\x20.field-hint\x20{\x20font-size:11px;\x20opacity:.45;\x20font-style:italic;\x20margin-top:2px;\x20grid-column:2;\x20}\x0a\x20\x20.dims-badge\x20{\x20display:inline-flex;\x20align-items:center;\x20gap:6px;\x20font-size:12px;\x20color:var(--okdb-accent);\x20background:color-mix(in\x20srgb,\x20var(--okdb-accent)\x207%,\x20transparent);\x20border:1px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-accent)\x2027%,\x20transparent);\x20border-radius:6px;\x20padding:3px\x2010px;\x20}\x0a\x20\x20.dims-badge-muted\x20{\x20color:#888;\x20border-color:var(--okdb-app-border);\x20background:transparent;\x20}\x0a\x20\x20.custom-model-box\x20{\x20background:var(--okdb-app-bg-deep);\x20border:1px\x20solid\x20var(--okdb-app-border);\x20border-radius:8px;\x20padding:10px\x2012px;\x20margin-top:4px;\x20display:flex;\x20flex-direction:column;\x20gap:8px;\x20}\x0a\x20\x20.custom-model-box\x20.row\x20{\x20display:flex;\x20gap:8px;\x20align-items:center;\x20}\x0a\x20\x20.custom-model-box\x20label\x20{\x20font-size:12px;\x20opacity:.6;\x20white-space:nowrap;\x20}\x0a\x20\x20.save-to-catalog\x20{\x20display:flex;\x20align-items:center;\x20gap:6px;\x20font-size:12px;\x20opacity:.7;\x20cursor:pointer;\x20}\x0a\x20\x20.save-to-catalog\x20input\x20{\x20cursor:pointer;\x20}\x0a','refreshOllamaModels','typeMap','status','defaultFieldMode','modelsForProvider','emb_custom','emb_config','idx','/embeddings/algorithms','ollama','refreshCatalogState','loadDeepForType','11hKzuIl','liveOllamaModels','\x20GB','concurrency','chunk','emb','30000','liveOllamaLoading','512','484yJVEiG','reconcileModelSelection','loadProviders','findModelEntry','type','json','effectiveModel','none','paths','lockedEnv','/env/','Model\x20is\x20required','loading'];_0x3dec=function(){return _0x16b6b5;};return _0x3dec();}function _0x340a(_0x9141ee,_0x41614d){_0x9141ee=_0x9141ee-0x1b0;const _0x3dece4=_0x3dec();let _0x340a47=_0x3dece4[_0x9141ee];return _0x340a47;}import _0x27ed36 from'./embed-model-catalog.ok.js';import _0x2e611b from'../modals/register-model-modal.ok.js';export default{'tag':_0x2524d7(0x1c2),'attr':{'locktype':{},'lockenv':{},'initialtab':{},'lockstoragekey':{},'lockembedder':{}},'dependencies':[_0x2dd769,_0x2e611b,_0x27ed36],'context':_0x3635a9=>({'tab':_0x2524d7(0x251),'busy':!0x1,'error':null,'success':null,get 'lockedType'(){const _0x5eeb8e=_0x2524d7;return _0x3635a9[_0x5eeb8e(0x201)][_0x5eeb8e(0x242)]||null;},get 'lockedEnv'(){const _0x15ddb7=_0x2524d7;return _0x3635a9[_0x15ddb7(0x201)]['lockenv']||_0x3635a9['$ok']?.['stores']?.[_0x15ddb7(0x1bc)]?.['selectedEnv']||'default';},get 'lockedStorageKey'(){const _0x104b27=_0x2524d7;return _0x3635a9['$attr'][_0x104b27(0x1f1)]||null;},get 'lockedEmbedder'(){const _0x4ce62d=_0x2524d7;return _0x3635a9[_0x4ce62d(0x201)][_0x4ce62d(0x1b3)]||null;},'types':[],'typeMap':{},'deepTypeMap':{},'modelCatalog':{},'liveOllamaModels':null,'liveOllamaLoading':!0x1,'liveOllamaError':null,'providers':[],'providerMap':{},'algorithms':[],'algorithmMap':{},async 'loadTypes'(){const _0x1bb188=_0x2524d7;try{const _0x438f00=this[_0x1bb188(0x225)],_0x42e015=await fetch(__ENV__['API']+'/env/'+encodeURIComponent(_0x438f00)+'/types'),_0x1b7249=(await _0x42e015[_0x1bb188(0x221)]())['data']||[];if(this['types']=Array[_0x1bb188(0x265)](_0x1b7249)?_0x1b7249['map'](_0x1ac5ba=>_0x1ac5ba[_0x1bb188(0x220)]??_0x1ac5ba[_0x1bb188(0x254)]??_0x1ac5ba)[_0x1bb188(0x1e6)](Boolean)[_0x1bb188(0x1fe)]():Object[_0x1bb188(0x252)](_0x1b7249)[_0x1bb188(0x1fe)](),this[_0x1bb188(0x208)]={},Array['isArray'](_0x1b7249)){for(const _0x1071db of _0x1b7249)_0x1071db['type']&&(this['typeMap'][_0x1071db[_0x1bb188(0x220)]]=_0x1071db[_0x1bb188(0x232)]||{});}else{for(const [_0x3ce8b9,_0x53ce2a]of Object[_0x1bb188(0x1c9)](_0x1b7249))this[_0x1bb188(0x208)][_0x3ce8b9]=_0x53ce2a[_0x1bb188(0x232)]||{};}}catch{this[_0x1bb188(0x1de)]=[],this['typeMap']={};}},async 'loadModelCatalog'(){const _0xaec7cb=_0x2524d7;try{const _0x1845f5=await fetch(__ENV__[_0xaec7cb(0x267)]+_0xaec7cb(0x247)),_0x32d05c=await _0x1845f5[_0xaec7cb(0x221)]();this[_0xaec7cb(0x25c)]=_0x32d05c[_0xaec7cb(0x1db)]??{};}catch{this[_0xaec7cb(0x25c)]={};}},async 'loadProviders'(){const _0x33e896=_0x2524d7;try{const _0x959b77=await fetch(__ENV__[_0x33e896(0x267)]+'/embeddings/providers'),_0x4531fd=await _0x959b77[_0x33e896(0x221)]();this[_0x33e896(0x1ea)]=_0x4531fd[_0x33e896(0x1db)]??[],this[_0x33e896(0x1b0)]={};for(const _0x2edf66 of this[_0x33e896(0x1ea)])this[_0x33e896(0x1b0)][_0x2edf66[_0x33e896(0x200)]]=_0x2edf66;}catch{this['providers']=[],this[_0x33e896(0x1b0)]={};}},async 'loadAlgorithms'(){const _0x21fcf5=_0x2524d7;try{const _0x14dc7f=await fetch(__ENV__['API']+_0x21fcf5(0x20f)),_0x4ec92c=await _0x14dc7f['json']();this['algorithms']=_0x4ec92c[_0x21fcf5(0x1db)]??[],this[_0x21fcf5(0x1f5)]={};for(const _0x3c0150 of this['algorithms'])this[_0x21fcf5(0x1f5)][_0x3c0150[_0x21fcf5(0x200)]]=_0x3c0150;}catch{this[_0x21fcf5(0x1b8)]=[],this['algorithmMap']={};}},async 'loadDeepForType'(_0x1373c8){const _0x39c5f2=_0x2524d7;if(_0x1373c8&&void 0x0===this[_0x39c5f2(0x1d2)][_0x1373c8]){this[_0x39c5f2(0x1d2)]={...this[_0x39c5f2(0x1d2)],[_0x1373c8]:{'paths':{},'loading':!0x0}};try{const _0x28bb05=this[_0x39c5f2(0x225)],_0x273ebe=await fetch(__ENV__[_0x39c5f2(0x267)]+_0x39c5f2(0x226)+encodeURIComponent(_0x28bb05)+_0x39c5f2(0x1da)+encodeURIComponent(_0x1373c8)+_0x39c5f2(0x229)),_0x569db6=await _0x273ebe[_0x39c5f2(0x221)]();this['deepTypeMap']={...this['deepTypeMap'],[_0x1373c8]:{'paths':(_0x569db6[_0x39c5f2(0x1db)]??_0x569db6[_0x39c5f2(0x205)])?.[_0x39c5f2(0x224)]??{},'loading':!0x1}};}catch{this[_0x39c5f2(0x1d2)]={...this['deepTypeMap'],[_0x1373c8]:{'paths':{},'loading':!0x1}};}}},async 'refreshOllamaModels'(_0x6a0bc){const _0x2ac73c=_0x2524d7;this[_0x2ac73c(0x21a)]=!0x0,this['liveOllamaError']=null;const _0x49d2c1=_0x6a0bc?.[_0x2ac73c(0x20d)]?.['url']??_0x6a0bc?.[_0x2ac73c(0x20d)]?.[_0x2ac73c(0x235)]??'',_0x3b479d=_0x49d2c1?'?url='+encodeURIComponent(_0x49d2c1):'';try{const _0x50a0f0=await fetch(__ENV__[_0x2ac73c(0x267)]+_0x2ac73c(0x256)+_0x3b479d),_0x19b3c0=await _0x50a0f0[_0x2ac73c(0x221)](),_0x268ab5=_0x19b3c0[_0x2ac73c(0x1db)]??_0x19b3c0[_0x2ac73c(0x205)]??{};if('error'!==_0x268ab5[_0x2ac73c(0x1df)]&&_0x268ab5[_0x2ac73c(0x253)]?.['length']){const _0x2a151c=new Map((this[_0x2ac73c(0x25c)][_0x2ac73c(0x210)]??[])[_0x2ac73c(0x1b2)](_0x1e4c93=>[_0x1e4c93[_0x2ac73c(0x24b)],_0x1e4c93]));this[_0x2ac73c(0x214)]=_0x268ab5[_0x2ac73c(0x253)][_0x2ac73c(0x1b2)](_0x100886=>{const _0x4d0b7a=_0x2ac73c,_0x5f2c2d=_0x100886[_0x4d0b7a(0x24b)]['split'](':')[0x0],_0x36965f=_0x2a151c[_0x4d0b7a(0x248)](_0x100886[_0x4d0b7a(0x24b)])??_0x2a151c[_0x4d0b7a(0x248)](_0x5f2c2d);return{'model':_0x100886[_0x4d0b7a(0x24b)],'dims':_0x36965f?.[_0x4d0b7a(0x1c3)]??null,'description':_0x100886['size']?(_0x100886[_0x4d0b7a(0x1fa)]/0x3b9aca00)[_0x4d0b7a(0x266)](0x1)+_0x4d0b7a(0x215):null,'builtin':!0x1,'live':!0x0};}),this['liveOllamaError']=null;}else this[_0x2ac73c(0x214)]=[],this[_0x2ac73c(0x25e)]=_0x268ab5['error']??'No\x20models\x20found\x20on\x20Ollama\x20server';}catch(_0x2e6844){this[_0x2ac73c(0x214)]=[],this['liveOllamaError']=_0x2e6844[_0x2ac73c(0x1ec)];}finally{this[_0x2ac73c(0x21a)]=!0x1;for(const _0x10db38 of[this['pl'],this[_0x2ac73c(0x218)]])_0x2ac73c(0x210)===_0x10db38?.[_0x2ac73c(0x1bf)]&&this[_0x2ac73c(0x21d)](_0x10db38);}},'modelLabel'(_0x1d2068){const _0x5cf7e4=_0x2524d7;let _0x55036f=_0x1d2068['live']?'●\x20'+_0x1d2068['model']:_0x1d2068[_0x5cf7e4(0x24b)];return _0x1d2068[_0x5cf7e4(0x1c3)]?_0x55036f+=_0x5cf7e4(0x268)+_0x1d2068['dims']+'\x20dims':_0x1d2068[_0x5cf7e4(0x260)]?_0x55036f+='\x20—\x20'+_0x1d2068[_0x5cf7e4(0x260)]:_0x1d2068[_0x5cf7e4(0x246)]&&(_0x55036f+=_0x5cf7e4(0x23c)),_0x55036f;},'modelsForProvider'(_0x46b489){const _0x3cc5a9=_0x2524d7;return'ollama'===_0x46b489&&Array['isArray'](this['liveOllamaModels'])&&this[_0x3cc5a9(0x214)][_0x3cc5a9(0x23a)]?this[_0x3cc5a9(0x214)]:this[_0x3cc5a9(0x25c)][_0x46b489]??[];},'findModelEntry'(_0x3158bf,_0x51c8cb){const _0x39e551=_0x2524d7;if(!_0x51c8cb||_0x39e551(0x1ca)===_0x51c8cb)return null;const _0xf1d542=this[_0x39e551(0x20b)](_0x3158bf),_0x5c5ae7=_0xf1d542[_0x39e551(0x1c0)](_0x573609=>_0x573609[_0x39e551(0x24b)]===_0x51c8cb);if(_0x5c5ae7)return _0x5c5ae7;const _0x11abdb=String(_0x51c8cb)[_0x39e551(0x1be)](':')[0x0];return _0xf1d542[_0x39e551(0x1c0)](_0x463090=>_0x463090['model']===_0x11abdb||String(_0x463090['model']||'')[_0x39e551(0x1be)](':')[0x0]===_0x11abdb)??null;},'clearModelSelection'(_0xbeedc4){const _0x2b032b=_0x2524d7;_0xbeedc4[_0x2b032b(0x1e2)]='',_0xbeedc4[_0x2b032b(0x1d4)]='',_0xbeedc4[_0x2b032b(0x22a)]=null,_0xbeedc4['emb_custom']=!0x1;},'reconcileModelSelection'(_0x8341f6){const _0x232fc6=_0x2524d7;if(!_0x8341f6)return;if('__custom__'===_0x8341f6[_0x232fc6(0x1e2)])return _0x8341f6[_0x232fc6(0x20c)]=!0x0,_0x8341f6[_0x232fc6(0x1d4)]='',void(_0x8341f6[_0x232fc6(0x22a)]=null);if(!_0x8341f6[_0x232fc6(0x1e2)])return void this[_0x232fc6(0x1cf)](_0x8341f6);const _0x3bfc07=this[_0x232fc6(0x21f)](_0x8341f6[_0x232fc6(0x1bf)],_0x8341f6[_0x232fc6(0x1e2)]);_0x3bfc07?(_0x8341f6[_0x232fc6(0x1e2)]=_0x3bfc07['model'],_0x8341f6[_0x232fc6(0x1d4)]=_0x3bfc07['model'],_0x8341f6[_0x232fc6(0x22a)]=_0x3bfc07['dims']??null,_0x8341f6[_0x232fc6(0x20c)]=!0x1):this[_0x232fc6(0x1cf)](_0x8341f6);},'providerFields'(_0x51094d){const _0x3e5e34=_0x2524d7;return this[_0x3e5e34(0x1b0)][_0x51094d]?.[_0x3e5e34(0x232)]??[];},'providerNote'(_0x5247d6){const _0x55d508=_0x2524d7;return this[_0x55d508(0x1b0)][_0x5247d6]?.['note']??null;},'algorithmFields'(_0x37bf8){const _0x5a7952=_0x2524d7;return this[_0x5a7952(0x1f5)][_0x37bf8]?.['fields']??[];},'algorithmNote'(_0x59a04f){const _0x2f92a1=_0x2524d7;return this[_0x2f92a1(0x1f5)][_0x59a04f]?.[_0x2f92a1(0x1d0)]??null;},'onAlgorithmChange'(_0x3fa23d,_0x44930f){const _0x41d205=_0x2524d7;_0x3fa23d[_0x41d205(0x262)]=_0x44930f,_0x3fa23d['alg_config']={};for(const _0x131bfa of this[_0x41d205(0x1cc)](_0x44930f))void 0x0!==_0x131bfa[_0x41d205(0x1f2)]&&(_0x3fa23d[_0x41d205(0x1ba)][_0x131bfa[_0x41d205(0x200)]]=_0x131bfa[_0x41d205(0x1f2)]);},'buildAlgorithmConfig'(_0x419327){const _0x4dcfb7=_0x2524d7,_0x18f352=this[_0x4dcfb7(0x1cc)](_0x419327[_0x4dcfb7(0x262)]??_0x4dcfb7(0x1d1)),_0x294141={};for(const _0x3f0475 of _0x18f352){const _0x2898c9=_0x419327['alg_config']?.[_0x3f0475[_0x4dcfb7(0x200)]];if(void 0x0===_0x2898c9||''===_0x2898c9)void 0x0!==_0x3f0475[_0x4dcfb7(0x1f2)]&&(_0x294141[_0x3f0475['key']]=_0x3f0475[_0x4dcfb7(0x1f2)]);else{const _0x39881c='number'===_0x3f0475[_0x4dcfb7(0x220)]?Number(_0x2898c9):String(_0x2898c9);if('number'===_0x3f0475[_0x4dcfb7(0x220)]&&isNaN(_0x39881c))continue;_0x294141[_0x3f0475[_0x4dcfb7(0x200)]]=_0x39881c;}}return _0x294141;},'buildProviderConfig'(_0x2b0739){const _0x5eebaf=_0x2524d7,_0x579891=this[_0x5eebaf(0x1d9)](_0x2b0739[_0x5eebaf(0x1bf)]??''),_0x30cfe6={};for(const _0x9dc3ee of _0x579891){const _0x8a3f95=_0x2b0739['emb_config']?.[_0x9dc3ee[_0x5eebaf(0x200)]];void 0x0===_0x8a3f95||''===_0x8a3f95?void 0x0!==_0x9dc3ee['default']&&(_0x30cfe6[_0x9dc3ee[_0x5eebaf(0x200)]]=_0x9dc3ee[_0x5eebaf(0x1f2)]):_0x30cfe6[_0x9dc3ee[_0x5eebaf(0x200)]]=_0x5eebaf(0x233)===_0x9dc3ee['type']?Number(_0x8a3f95):String(_0x8a3f95);}return _0x30cfe6;},'getFields'(_0x5e6dbb,_0xe603b4){const _0x2a8ffc=_0x2524d7,_0x4cb98c=this[_0x2a8ffc(0x1d2)][_0x5e6dbb];if(_0x4cb98c&&!_0x4cb98c[_0x2a8ffc(0x228)]&&Object['keys'](_0x4cb98c[_0x2a8ffc(0x224)])[_0x2a8ffc(0x23a)]>0x0){const _0x54c199=Object[_0x2a8ffc(0x252)](_0x4cb98c[_0x2a8ffc(0x224)]);return'text'===_0xe603b4?_0x54c199[_0x2a8ffc(0x1e6)](_0x2690da=>_0x4cb98c[_0x2a8ffc(0x224)][_0x2690da][_0x2a8ffc(0x269)](_0x2a8ffc(0x1cd)))['sort']():_0x54c199[_0x2a8ffc(0x1fe)]();}const _0x5aa313=this['typeMap'][_0x5e6dbb]||{},_0x2942ed=Object['keys'](_0x5aa313);return'text'===_0xe603b4?_0x2942ed['filter'](_0x320b87=>_0x5aa313[_0x320b87][_0x2a8ffc(0x269)]('string')):_0x2942ed[_0x2a8ffc(0x1fe)]();},'defaultFieldMode'(_0x53d64f){const _0x26c112=_0x2524d7,_0x5bd6e6=this[_0x26c112(0x1d2)][_0x53d64f];if(_0x5bd6e6&&!_0x5bd6e6[_0x26c112(0x228)]&&Object[_0x26c112(0x252)](_0x5bd6e6[_0x26c112(0x224)])[_0x26c112(0x23a)]>0x0){const _0x2f4c36=Object['keys'](_0x5bd6e6[_0x26c112(0x224)]);return _0x2f4c36['length']?_0x2f4c36['some'](_0x32ac69=>_0x5bd6e6[_0x26c112(0x224)][_0x32ac69]['includes']('string'))?_0x26c112(0x1b5):'all':_0x26c112(0x26c);}const _0x17962a=this[_0x26c112(0x208)][_0x53d64f]||{},_0x28ab71=Object['keys'](_0x17962a);return _0x28ab71[_0x26c112(0x23a)]?_0x28ab71['some'](_0x4747b4=>_0x17962a[_0x4747b4][_0x26c112(0x269)](_0x26c112(0x1cd)))?'text':'all':_0x26c112(0x26c);},'getFieldItems'(_0x110e14,_0x33b160){const _0xc88d9f=_0x2524d7,_0x15bf1a=this[_0xc88d9f(0x1d2)][_0x110e14];let _0x1317d6;return _0x1317d6=_0x15bf1a&&!_0x15bf1a['loading']&&Object['keys'](_0x15bf1a[_0xc88d9f(0x224)])[_0xc88d9f(0x23a)]>0x0?Object[_0xc88d9f(0x1c9)](_0x15bf1a[_0xc88d9f(0x224)]):Object[_0xc88d9f(0x1c9)](this[_0xc88d9f(0x208)][_0x110e14]||{})[_0xc88d9f(0x1b2)](([_0x51672d,_0xea0746])=>[_0x51672d,_0xea0746]),_0xc88d9f(0x1b5)===_0x33b160&&(_0x1317d6=_0x1317d6['filter'](([,_0x46b1f4])=>_0x46b1f4['includes']('string'))),_0x1317d6[_0xc88d9f(0x1b2)](([_0x3294e2,_0x5010f9])=>({'path':_0x3294e2,'types':Array['isArray'](_0x5010f9)?_0x5010f9:[_0x5010f9],'hint':Array[_0xc88d9f(0x265)](_0x5010f9)&&_0x5010f9[_0xc88d9f(0x269)](_0xc88d9f(0x1c7))?_0xc88d9f(0x1c7):null}));},'onProviderChange'(_0x2613f2,_0x1a3fd3){const _0x3a2ac1=_0x2524d7;_0x2613f2[_0x3a2ac1(0x1bf)]=_0x1a3fd3,_0x2613f2['emb_config']={};for(const _0x9097d7 of this[_0x3a2ac1(0x1d9)](_0x1a3fd3))void 0x0!==_0x9097d7[_0x3a2ac1(0x1f2)]&&(_0x2613f2[_0x3a2ac1(0x20d)][_0x9097d7['key']]=_0x9097d7['default']);_0x3a2ac1(0x210)!==_0x1a3fd3||null!==this[_0x3a2ac1(0x214)]||this[_0x3a2ac1(0x21a)]||this[_0x3a2ac1(0x207)](_0x2613f2),this[_0x3a2ac1(0x1cf)](_0x2613f2),_0x2613f2[_0x3a2ac1(0x234)]='',_0x2613f2[_0x3a2ac1(0x250)]='',_0x2613f2[_0x3a2ac1(0x237)]=!0x1;},'onModelSelChange'(_0x46870b,_0x40ae33){const _0x3f3518=_0x2524d7;if(_0x46870b[_0x3f3518(0x1e2)]=_0x40ae33,_0x40ae33){if('__custom__'===_0x40ae33)_0x46870b[_0x3f3518(0x20c)]=!0x0,_0x46870b[_0x3f3518(0x1d4)]='',_0x46870b[_0x3f3518(0x22a)]=null;else{_0x46870b[_0x3f3518(0x20c)]=!0x1,_0x46870b[_0x3f3518(0x1d4)]=_0x40ae33;const _0x3b0ef3=this[_0x3f3518(0x21f)](_0x46870b[_0x3f3518(0x1bf)],_0x40ae33);_0x46870b['emb_dims_auto']=_0x3b0ef3?.['dims']??null,_0x46870b[_0x3f3518(0x234)]='',_0x46870b[_0x3f3518(0x250)]='',_0x46870b['emb_save_catalog']=!0x1;}}else this[_0x3f3518(0x1cf)](_0x46870b);},'effectiveModel':_0x3ed400=>_0x3ed400['emb_custom']?_0x3ed400[_0x2524d7(0x234)]['trim']():_0x3ed400['emb_model'],'effectiveDims'(_0x64e640){const _0x5e465e=_0x2524d7;if(_0x64e640[_0x5e465e(0x20c)]){const _0xc4fe8f=Number(_0x64e640['emb_custom_dims']);return Number[_0x5e465e(0x263)](_0xc4fe8f)&&_0xc4fe8f>0x0?_0xc4fe8f:null;}return _0x64e640['emb_dims_auto']??null;},async 'maybeSaveToCatalog'(_0x3f38f4){const _0x731c36=_0x2524d7;if(!_0x3f38f4[_0x731c36(0x20c)]||!_0x3f38f4[_0x731c36(0x237)])return!0x0;const _0x42e0d6=_0x3f38f4['emb_custom_model']['trim'](),_0x56f7b9=Number(_0x3f38f4[_0x731c36(0x250)]);if(!_0x42e0d6||!_0x56f7b9)return!0x0;try{await fetch(__ENV__['API']+_0x731c36(0x247),{'method':'POST','headers':{'Content-Type':_0x731c36(0x1b9)},'body':JSON[_0x731c36(0x1b1)]({'provider':_0x3f38f4[_0x731c36(0x1bf)],'model':_0x42e0d6,'dims':_0x56f7b9})}),await this['loadModelCatalog']();}catch{}return!0x0;},async 'openRegisterModel'(_0x1493df){const _0xbd2dee=_0x2524d7;await _0x3635a9[_0xbd2dee(0x22f)][_0xbd2dee(0x26a)][_0xbd2dee(0x1e8)][_0xbd2dee(0x1e1)]({'owner':_0x3635a9,'title':_0xbd2dee(0x1ce),'content':_0xbd2dee(0x1fb),'context':_0x3aa070=>({'modal':_0x3aa070,'initialProvider':_0x1493df?.['emb_type']??'','onDone':async()=>{const _0x482bbf=_0xbd2dee;await this[_0x482bbf(0x211)](_0x1493df);}})});},async 'refreshCatalogState'(_0x33711d){const _0x59f50f=_0x2524d7;await this[_0x59f50f(0x204)](),_0x33711d&&(_0x59f50f(0x210)===(_0x33711d?.[_0x59f50f(0x1bf)]??'')&&Array[_0x59f50f(0x265)](this[_0x59f50f(0x214)])&&this[_0x59f50f(0x214)]['length']||_0x33711d[_0x59f50f(0x1e2)])&&this[_0x59f50f(0x21d)](_0x33711d);},async 'openModelCatalog'(_0x4ab23a){const _0x199edc=_0x2524d7;await _0x3635a9['$ok'][_0x199edc(0x26a)][_0x199edc(0x1e8)][_0x199edc(0x1e1)]({'owner':_0x3635a9,'title':_0x199edc(0x22b),'content':_0x199edc(0x257),'context':()=>({'initialProvider':_0x4ab23a?.[_0x199edc(0x1bf)]??'','onChanged':async()=>{await this['refreshCatalogState'](_0x4ab23a);}})});},'pl':{'name':'','source_type':'','field':'','field_mode':_0x2524d7(0x26c),'mode':_0x2524d7(0x203),'emb_type':'','emb_model_sel':'','emb_model':'','emb_dims_auto':null,'emb_custom':!0x1,'emb_custom_model':'','emb_custom_dims':'','emb_save_catalog':!0x1,'emb_config':{},'w_concurrency':'1','w_poll_interval':_0x2524d7(0x1fc),'algorithm':_0x2524d7(0x1d1),'alg_config':{},'prepare':_0x2524d7(0x223),'prepare_custom':'','chunk_strategy':_0x2524d7(0x1b6),'chunk_custom':'','chunk_size':_0x2524d7(0x21b),'chunk_overlap':'64','chunk_store_text':!0x0},'onPlSourceTypeChange'(_0x4ee9f6){const _0x43e438=_0x2524d7;this['pl'][_0x43e438(0x1dc)]=_0x4ee9f6,this['pl']['field']='',this['pl'][_0x43e438(0x22c)]=this['defaultFieldMode'](_0x4ee9f6),this[_0x43e438(0x212)](_0x4ee9f6);},'setPlFieldMode'(_0x4aac98){const _0xbd4b10=_0x2524d7;this['pl'][_0xbd4b10(0x22c)]=_0x4aac98,this['pl'][_0xbd4b10(0x239)]='';},'idx':{'name':'','source_type':'','embedder':'','storage_key':'','field':'','field_mode':_0x2524d7(0x26c),'dims':'','mode':_0x2524d7(0x203),'job_type':''},'onIdxSourceTypeChange'(_0x4a5888){const _0x45357f=_0x2524d7;this[_0x45357f(0x20e)][_0x45357f(0x1dc)]=_0x4a5888,this['idx'][_0x45357f(0x239)]='',this[_0x45357f(0x20e)][_0x45357f(0x22c)]=this[_0x45357f(0x20a)](_0x4a5888),this[_0x45357f(0x212)](_0x4a5888);},'setIdxFieldMode'(_0x195a0b){const _0x3164d7=_0x2524d7;this[_0x3164d7(0x20e)][_0x3164d7(0x22c)]=_0x195a0b,this[_0x3164d7(0x20e)]['field']='';},'emb':{'name':'','emb_type':'','emb_model_sel':'','emb_model':'','emb_dims_auto':null,'emb_custom':!0x1,'emb_custom_model':'','emb_custom_dims':'','emb_save_catalog':!0x1,'emb_config':{}},'srch':{'name':'','source_type':'','storage_key':'','dims':'','embedder':'','algorithm':_0x2524d7(0x1d1),'alg_config':{}},'wkr':{'name':'','job_type':'','indexer':'','embedder':'','concurrency':'1','pollInterval':'1000','ttl':_0x2524d7(0x219)},'setTab'(_0x8e4704){const _0x1629cb=_0x2524d7;this[_0x1629cb(0x230)]=_0x8e4704,this['error']=null,this['success']=null;},'num'(_0x239eb6){const _0x165c74=Number(_0x239eb6);return isNaN(_0x165c74)||''===_0x239eb6?void 0x0:_0x165c74;},async 'submitPipeline'(){const _0x2406c1=_0x2524d7,_0x1bb2a8=this['pl'];if(!_0x1bb2a8['name'][_0x2406c1(0x25b)]())return this[_0x2406c1(0x258)]=_0x2406c1(0x23b);if(!_0x1bb2a8[_0x2406c1(0x1dc)]['trim']())return this[_0x2406c1(0x258)]=_0x2406c1(0x238);const _0x1c5d73=this['effectiveModel'](_0x1bb2a8),_0x3fd7f3=this[_0x2406c1(0x1ef)](_0x1bb2a8);if(!_0x1c5d73)return this[_0x2406c1(0x258)]=_0x2406c1(0x227);if(_0x1bb2a8[_0x2406c1(0x20c)]&&!_0x3fd7f3)return this['error']=_0x2406c1(0x1f7);for(const _0x4cc434 of this[_0x2406c1(0x1d9)](_0x1bb2a8[_0x2406c1(0x1bf)]))if(_0x4cc434[_0x2406c1(0x22e)]&&!_0x1bb2a8['emb_config'][_0x4cc434[_0x2406c1(0x200)]]?.['toString']()[_0x2406c1(0x25b)]())return this[_0x2406c1(0x258)]=_0x4cc434[_0x2406c1(0x245)]+_0x2406c1(0x255);await this[_0x2406c1(0x1f0)](_0x1bb2a8);const _0x299cf1=this[_0x2406c1(0x225)],_0x214b19=_0x1bb2a8[_0x2406c1(0x1dc)]['trim'](),_0x5289ff={'name':_0x1bb2a8[_0x2406c1(0x254)][_0x2406c1(0x25b)](),'field':_0x1bb2a8['field'][_0x2406c1(0x25b)]()||void 0x0,'dims':_0x3fd7f3??void 0x0,'mode':_0x1bb2a8[_0x2406c1(0x1cb)],'embedder':{'type':_0x1bb2a8[_0x2406c1(0x1bf)],'model':_0x1c5d73||void 0x0,...this[_0x2406c1(0x244)](_0x1bb2a8)},'algorithm':_0x1bb2a8[_0x2406c1(0x262)]},_0x5862a5=this['buildAlgorithmConfig'](_0x1bb2a8);if(Object[_0x2406c1(0x252)](_0x5862a5)[_0x2406c1(0x23a)]&&(_0x5289ff[_0x2406c1(0x243)]=_0x5862a5),'queue'===_0x1bb2a8[_0x2406c1(0x1cb)]&&(_0x5289ff[_0x2406c1(0x1d7)]={'concurrency':this['num'](_0x1bb2a8[_0x2406c1(0x1ff)]),'pollInterval':this[_0x2406c1(0x1e7)](_0x1bb2a8[_0x2406c1(0x24d)])}),_0x1bb2a8[_0x2406c1(0x239)][_0x2406c1(0x25b)]()&&_0x2406c1(0x223)!==_0x1bb2a8[_0x2406c1(0x1dd)]&&(_0x5289ff['prepare']=_0x2406c1(0x26c)===_0x1bb2a8[_0x2406c1(0x1dd)]?_0x1bb2a8[_0x2406c1(0x1d6)][_0x2406c1(0x25b)]():_0x1bb2a8[_0x2406c1(0x1dd)]),_0x1bb2a8[_0x2406c1(0x239)][_0x2406c1(0x25b)]()&&'off'!==_0x1bb2a8[_0x2406c1(0x1bb)]){const _0x556b30=_0x2406c1(0x26c)===_0x1bb2a8[_0x2406c1(0x1bb)]?_0x1bb2a8[_0x2406c1(0x1fd)][_0x2406c1(0x25b)]():_0x1bb2a8['chunk_strategy'];_0x5289ff[_0x2406c1(0x217)]={'strategy':_0x556b30,'size':this[_0x2406c1(0x1e7)](_0x1bb2a8[_0x2406c1(0x24a)])??0x200,'overlap':'fixed'===_0x1bb2a8[_0x2406c1(0x1bb)]?this['num'](_0x1bb2a8[_0x2406c1(0x1c4)])??0x40:void 0x0,'storeText':_0x1bb2a8[_0x2406c1(0x1f6)]},void 0x0===_0x5289ff[_0x2406c1(0x217)][_0x2406c1(0x240)]&&delete _0x5289ff['chunk'][_0x2406c1(0x240)];}await this[_0x2406c1(0x1c5)](_0x2406c1(0x226)+encodeURIComponent(_0x299cf1)+_0x2406c1(0x1da)+encodeURIComponent(_0x214b19)+'/pipelines',_0x5289ff);},async 'submitEmbedder'(){const _0x37c3e0=_0x2524d7,_0x3bc832=this[_0x37c3e0(0x218)];if(!_0x3bc832[_0x37c3e0(0x254)]['trim']())return this[_0x37c3e0(0x258)]=_0x37c3e0(0x23b);const _0x26e2a2=this[_0x37c3e0(0x222)](_0x3bc832);if(!_0x26e2a2)return this[_0x37c3e0(0x258)]=_0x37c3e0(0x227);for(const _0xe54a5d of this['providerFields'](_0x3bc832[_0x37c3e0(0x1bf)]))if(_0xe54a5d['required']&&!_0x3bc832[_0x37c3e0(0x20d)][_0xe54a5d['key']]?.[_0x37c3e0(0x1c1)]()[_0x37c3e0(0x25b)]())return this['error']=_0xe54a5d[_0x37c3e0(0x245)]+_0x37c3e0(0x255);await this[_0x37c3e0(0x1f0)](_0x3bc832);const _0x3941e5={'name':_0x3bc832[_0x37c3e0(0x254)][_0x37c3e0(0x25b)](),'type':_0x3bc832['emb_type'],'model':_0x26e2a2||void 0x0,...this[_0x37c3e0(0x244)](_0x3bc832)};await this[_0x37c3e0(0x1c5)](_0x37c3e0(0x1f9),_0x3941e5);},async 'submitIndexer'(){const _0x1c4b17=_0x2524d7,_0x5ee57a=this[_0x1c4b17(0x20e)];if(!_0x5ee57a[_0x1c4b17(0x254)]['trim']())return this[_0x1c4b17(0x258)]='Name\x20is\x20required';if(!_0x5ee57a[_0x1c4b17(0x1dc)][_0x1c4b17(0x25b)]())return this[_0x1c4b17(0x258)]=_0x1c4b17(0x238);if(!_0x5ee57a[_0x1c4b17(0x236)][_0x1c4b17(0x25b)]())return this[_0x1c4b17(0x258)]=_0x1c4b17(0x1ee);const _0x3dd45c={'name':_0x5ee57a[_0x1c4b17(0x254)][_0x1c4b17(0x25b)](),'source_env':this[_0x1c4b17(0x225)],'source_type':_0x5ee57a[_0x1c4b17(0x1dc)]['trim'](),'embedder':_0x5ee57a[_0x1c4b17(0x236)][_0x1c4b17(0x25b)](),'storage_key':_0x5ee57a[_0x1c4b17(0x264)][_0x1c4b17(0x25b)]()||void 0x0,'field':_0x5ee57a[_0x1c4b17(0x239)][_0x1c4b17(0x25b)]()||void 0x0,'dims':this[_0x1c4b17(0x1e7)](_0x5ee57a['dims']),'mode':_0x5ee57a[_0x1c4b17(0x1cb)],'job_type':_0x5ee57a[_0x1c4b17(0x1ed)][_0x1c4b17(0x25b)]()||void 0x0};await this[_0x1c4b17(0x1c5)](_0x1c4b17(0x25f),_0x3dd45c);},async 'submitSearch'(){const _0x49976f=_0x2524d7,_0xc12934=this['srch'];if(!_0xc12934[_0x49976f(0x254)]['trim']())return this[_0x49976f(0x258)]=_0x49976f(0x23b);const _0x1db11a=(this[_0x49976f(0x1f3)]??_0xc12934['source_type']??'')[_0x49976f(0x25b)]();if(!_0x1db11a)return this['error']=_0x49976f(0x238);if(!_0xc12934['storage_key'][_0x49976f(0x25b)]())return this[_0x49976f(0x258)]='Storage\x20key\x20is\x20required';const _0x5844f9={'name':_0xc12934[_0x49976f(0x254)][_0x49976f(0x25b)](),'source_type':_0x1db11a,'source_env':this[_0x49976f(0x225)],'storage_key':_0xc12934[_0x49976f(0x264)][_0x49976f(0x25b)](),'dims':_0xc12934['dims']?Number(_0xc12934['dims']):void 0x0,'embedder':_0xc12934[_0x49976f(0x236)][_0x49976f(0x25b)]()||void 0x0,'algorithm':_0xc12934[_0x49976f(0x262)]},_0xa61829=this[_0x49976f(0x1e4)](_0xc12934);Object['keys'](_0xa61829)[_0x49976f(0x23a)]&&(_0x5844f9[_0x49976f(0x243)]=_0xa61829),await this[_0x49976f(0x1c5)](_0x49976f(0x24c),_0x5844f9);},async 'submitWorker'(){const _0x2bd81e=_0x2524d7,_0x4d82ce=this['wkr'];if(!_0x4d82ce[_0x2bd81e(0x254)]['trim']())return this[_0x2bd81e(0x258)]=_0x2bd81e(0x23b);if(!_0x4d82ce[_0x2bd81e(0x1ed)][_0x2bd81e(0x25b)]())return this[_0x2bd81e(0x258)]='Job\x20type\x20is\x20required';if(!_0x4d82ce['indexer'][_0x2bd81e(0x25b)]())return this[_0x2bd81e(0x258)]='Indexer\x20name\x20is\x20required';if(!_0x4d82ce[_0x2bd81e(0x236)][_0x2bd81e(0x25b)]())return this[_0x2bd81e(0x258)]='Embedder\x20name\x20is\x20required';const _0x1d17e3={'name':_0x4d82ce[_0x2bd81e(0x254)][_0x2bd81e(0x25b)](),'job_type':_0x4d82ce[_0x2bd81e(0x1ed)][_0x2bd81e(0x25b)](),'indexer':_0x4d82ce[_0x2bd81e(0x1d8)][_0x2bd81e(0x25b)](),'embedder':_0x4d82ce['embedder']['trim'](),'concurrency':this['num'](_0x4d82ce[_0x2bd81e(0x216)]),'pollInterval':this[_0x2bd81e(0x1e7)](_0x4d82ce[_0x2bd81e(0x1bd)]),'ttl':this[_0x2bd81e(0x1e7)](_0x4d82ce[_0x2bd81e(0x24e)])};await this['_post'](_0x2bd81e(0x1e9),_0x1d17e3);},async '_post'(_0x4652f1,_0x29b2c6){const _0x56fced=_0x2524d7;this[_0x56fced(0x24f)]=!0x0,this['error']=null,this[_0x56fced(0x1e0)]=null;try{const _0x155d81=await fetch(''+__ENV__['API']+_0x4652f1,{'method':_0x56fced(0x1d5),'headers':{'Content-Type':_0x56fced(0x1b9)},'body':JSON[_0x56fced(0x1b1)](_0x29b2c6)}),_0x35cd60=await _0x155d81[_0x56fced(0x221)]();if(!_0x155d81['ok']){const _0x1d0209=_0x35cd60?.[_0x56fced(0x258)]?.[_0x56fced(0x1ec)]||_0x35cd60?.[_0x56fced(0x1ec)]||'HTTP\x20'+_0x155d81[_0x56fced(0x209)];return void(this[_0x56fced(0x258)]=_0x1d0209[_0x56fced(0x269)](_0x56fced(0x1eb))?_0x56fced(0x1b4)+_0x29b2c6['name']+'\x22\x20already\x20exists.':_0x1d0209);}this['success']=_0x35cd60[_0x56fced(0x1db)],_0x3635a9[_0x56fced(0x22f)][_0x56fced(0x26a)]?.[_0x56fced(0x23f)]?.[_0x56fced(0x1e0)]?.(_0x56fced(0x1c8)),_0x3635a9['$dispatch']('created',_0x35cd60[_0x56fced(0x1db)]);}catch(_0x2fceff){this[_0x56fced(0x258)]=_0x2fceff?.[_0x56fced(0x1ec)]||String(_0x2fceff);}finally{this['busy']=!0x1;}},'handleSubmit'(){const _0x170baa=_0x2524d7;switch(this[_0x170baa(0x230)]){case'pipeline':return this['submitPipeline']();case'embedder':return this[_0x170baa(0x249)]();case _0x170baa(0x1d8):return this[_0x170baa(0x1e5)]();case _0x170baa(0x22d):return this[_0x170baa(0x1e3)]();case'worker':return this[_0x170baa(0x23d)]();}}}),async 'init'(_0x580459){const _0x57b607=_0x2524d7;await Promise['all']([this['loadTypes'](),this[_0x57b607(0x204)](),this[_0x57b607(0x21e)](),this['loadAlgorithms']()]);const _0x2bc962=_0x580459['$attr'][_0x57b607(0x1f8)];_0x2bc962&&[_0x57b607(0x251),'embedder',_0x57b607(0x1d8),_0x57b607(0x22d),_0x57b607(0x1d7)][_0x57b607(0x269)](_0x2bc962)&&(this[_0x57b607(0x230)]=_0x2bc962);const _0x4d2f12=_0x580459['$attr'][_0x57b607(0x242)];_0x4d2f12&&(this['pl'][_0x57b607(0x1dc)]=_0x4d2f12,this['pl'][_0x57b607(0x22c)]=this[_0x57b607(0x20a)](_0x4d2f12),this[_0x57b607(0x20e)]['source_type']=_0x4d2f12,this[_0x57b607(0x20e)][_0x57b607(0x22c)]=this[_0x57b607(0x20a)](_0x4d2f12),this[_0x57b607(0x261)][_0x57b607(0x1dc)]=_0x4d2f12,this[_0x57b607(0x212)](_0x4d2f12)),this[_0x57b607(0x231)]&&(this[_0x57b607(0x261)][_0x57b607(0x264)]=this[_0x57b607(0x231)]),this[_0x57b607(0x1f4)]&&(this['srch'][_0x57b607(0x236)]=this[_0x57b607(0x1f4)]);const _0x29958d=this[_0x57b607(0x1ea)][0x0]?.['key']??'';for(const _0x26511e of[this['pl'],this[_0x57b607(0x218)]]){_0x26511e[_0x57b607(0x1bf)]=_0x29958d,_0x26511e[_0x57b607(0x20d)]={};for(const _0x2b2eda of this['providerFields'](_0x29958d))void 0x0!==_0x2b2eda[_0x57b607(0x1f2)]&&(_0x26511e[_0x57b607(0x20d)][_0x2b2eda[_0x57b607(0x200)]]=_0x2b2eda[_0x57b607(0x1f2)]);this[_0x57b607(0x1cf)](_0x26511e);}_0x57b607(0x210)===_0x29958d&&this['refreshOllamaModels'](this['pl']);for(const _0x2276d3 of[this['pl'],this[_0x57b607(0x261)]])for(const _0x45e0a5 of this[_0x57b607(0x1cc)](_0x2276d3[_0x57b607(0x262)]))void 0x0!==_0x45e0a5['default']&&(_0x2276d3[_0x57b607(0x1ba)][_0x45e0a5[_0x57b607(0x200)]]=_0x45e0a5[_0x57b607(0x1f2)]);},'template':_0x2524d7(0x1d3),'style':_0x2524d7(0x206)};
1
+ import e from"../../../components/field-path-input.ok.js";import t from"./embed-model-catalog.ok.js";import n from"../modals/register-model-modal.ok.js";export default{tag:"embed-create-panel",attr:{locktype:{},lockenv:{},initialtab:{},lockstoragekey:{},lockembedder:{}},dependencies:[e,n,t],context:e=>({tab:"pipeline",busy:!1,error:null,success:null,get lockedType(){return e.$attr.locktype||null},get lockedEnv(){return e.$attr.lockenv||e.$ok?.stores?.okdb?.selectedEnv||"default"},get lockedStorageKey(){return e.$attr.lockstoragekey||null},get lockedEmbedder(){return e.$attr.lockembedder||null},types:[],typeMap:{},deepTypeMap:{},modelCatalog:{},liveOllamaModels:null,liveOllamaLoading:!1,liveOllamaError:null,providers:[],providerMap:{},algorithms:[],algorithmMap:{},async loadTypes(){try{const e=this.lockedEnv,t=await fetch(`${__ENV__.API}/env/${encodeURIComponent(e)}/types`),n=(await t.json()).data||[];if(this.types=Array.isArray(n)?n.map(e=>e.type??e.name??e).filter(Boolean).sort():Object.keys(n).sort(),this.typeMap={},Array.isArray(n))for(const e of n)e.type&&(this.typeMap[e.type]=e.fields||{});else for(const[e,t]of Object.entries(n))this.typeMap[e]=t.fields||{}}catch{this.types=[],this.typeMap={}}},async loadModelCatalog(){try{const e=await fetch(`${__ENV__.API}/embeddings/models`),t=await e.json();this.modelCatalog=t.data??{}}catch{this.modelCatalog={}}},async loadProviders(){try{const e=await fetch(`${__ENV__.API}/embeddings/providers`),t=await e.json();this.providers=t.data??[],this.providerMap={};for(const e of this.providers)this.providerMap[e.key]=e}catch{this.providers=[],this.providerMap={}}},async loadAlgorithms(){try{const e=await fetch(`${__ENV__.API}/embeddings/algorithms`),t=await e.json();this.algorithms=t.data??[],this.algorithmMap={};for(const e of this.algorithms)this.algorithmMap[e.key]=e}catch{this.algorithms=[],this.algorithmMap={}}},async loadDeepForType(e){if(e&&void 0===this.deepTypeMap[e]){this.deepTypeMap={...this.deepTypeMap,[e]:{paths:{},loading:!0}};try{const t=this.lockedEnv,n=await fetch(`${__ENV__.API}/env/${encodeURIComponent(t)}/type/${encodeURIComponent(e)}/deep-properties`),l=await n.json();this.deepTypeMap={...this.deepTypeMap,[e]:{paths:(l.data??l.result)?.paths??{},loading:!1}}}catch{this.deepTypeMap={...this.deepTypeMap,[e]:{paths:{},loading:!1}}}}},async refreshOllamaModels(e){this.liveOllamaLoading=!0,this.liveOllamaError=null;const t=e?.emb_config?.url??e?.emb_config?.baseUrl??"",n=t?`?url=${encodeURIComponent(t)}`:"";try{const e=await fetch(`${__ENV__.API}/embeddings/probe-ollama-models${n}`),t=await e.json(),l=t.data??t.result??{};if("error"!==l.source&&l.models?.length){const e=new Map((this.modelCatalog.ollama??[]).map(e=>[e.model,e]));this.liveOllamaModels=l.models.map(t=>{const n=t.model.split(":")[0],l=e.get(t.model)??e.get(n);return{model:t.model,dims:l?.dims??null,description:t.size?(t.size/1e9).toFixed(1)+" GB":null,builtin:!1,live:!0}}),this.liveOllamaError=null}else this.liveOllamaModels=[],this.liveOllamaError=l.error??"No models found on Ollama server"}catch(e){this.liveOllamaModels=[],this.liveOllamaError=e.message}finally{this.liveOllamaLoading=!1;for(const e of[this.pl,this.emb])"ollama"===e?.emb_type&&this.reconcileModelSelection(e)}},modelLabel(e){let t=e.live?`● ${e.model}`:e.model;return e.dims?t+=` — ${e.dims} dims`:e.description?t+=` — ${e.description}`:e.live&&(t+=" — ? dims"),t},modelsForProvider(e){return"ollama"===e&&Array.isArray(this.liveOllamaModels)&&this.liveOllamaModels.length?this.liveOllamaModels:this.modelCatalog[e]??[]},findModelEntry(e,t){if(!t||"__custom__"===t)return null;const n=this.modelsForProvider(e),l=n.find(e=>e.model===t);if(l)return l;const i=String(t).split(":")[0];return n.find(e=>e.model===i||String(e.model||"").split(":")[0]===i)??null},clearModelSelection(e){e.emb_model_sel="",e.emb_model="",e.emb_dims_auto=null,e.emb_custom=!1},reconcileModelSelection(e){if(!e)return;if("__custom__"===e.emb_model_sel)return e.emb_custom=!0,e.emb_model="",void(e.emb_dims_auto=null);if(!e.emb_model_sel)return void this.clearModelSelection(e);const t=this.findModelEntry(e.emb_type,e.emb_model_sel);t?(e.emb_model_sel=t.model,e.emb_model=t.model,e.emb_dims_auto=t.dims??null,e.emb_custom=!1):this.clearModelSelection(e)},providerFields(e){return this.providerMap[e]?.fields??[]},providerNote(e){return this.providerMap[e]?.note??null},algorithmFields(e){return this.algorithmMap[e]?.fields??[]},algorithmNote(e){return this.algorithmMap[e]?.note??null},onAlgorithmChange(e,t){e.algorithm=t,e.alg_config={};for(const n of this.algorithmFields(t))void 0!==n.default&&(e.alg_config[n.key]=n.default)},buildAlgorithmConfig(e){const t=this.algorithmFields(e.algorithm??"flat"),n={};for(const l of t){const t=e.alg_config?.[l.key];if(void 0===t||""===t)void 0!==l.default&&(n[l.key]=l.default);else{const e="number"===l.type?Number(t):String(t);if("number"===l.type&&isNaN(e))continue;n[l.key]=e}}return n},buildProviderConfig(e){const t=this.providerFields(e.emb_type??""),n={};for(const l of t){const t=e.emb_config?.[l.key];void 0===t||""===t?void 0!==l.default&&(n[l.key]=l.default):n[l.key]="number"===l.type?Number(t):String(t)}return n},getFields(e,t){const n=this.deepTypeMap[e];if(n&&!n.loading&&Object.keys(n.paths).length>0){const e=Object.keys(n.paths);return"text"===t?e.filter(e=>n.paths[e].includes("string")).sort():e.sort()}const l=this.typeMap[e]||{},i=Object.keys(l);return"text"===t?i.filter(e=>l[e].includes("string")):i.sort()},defaultFieldMode(e){const t=this.deepTypeMap[e];if(t&&!t.loading&&Object.keys(t.paths).length>0){const e=Object.keys(t.paths);return e.length?e.some(e=>t.paths[e].includes("string"))?"text":"all":"custom"}const n=this.typeMap[e]||{},l=Object.keys(n);return l.length?l.some(e=>n[e].includes("string"))?"text":"all":"custom"},getFieldItems(e,t){const n=this.deepTypeMap[e];let l;return l=n&&!n.loading&&Object.keys(n.paths).length>0?Object.entries(n.paths):Object.entries(this.typeMap[e]||{}).map(([e,t])=>[e,t]),"text"===t&&(l=l.filter(([,e])=>e.includes("string"))),l.map(([e,t])=>({path:e,types:Array.isArray(t)?t:[t],hint:Array.isArray(t)&&t.includes("geo")?"geo":null}))},onProviderChange(e,t){e.emb_type=t,e.emb_config={};for(const n of this.providerFields(t))void 0!==n.default&&(e.emb_config[n.key]=n.default);"ollama"!==t||null!==this.liveOllamaModels||this.liveOllamaLoading||this.refreshOllamaModels(e),this.clearModelSelection(e),e.emb_custom_model="",e.emb_custom_dims="",e.emb_save_catalog=!1},onModelSelChange(e,t){if(e.emb_model_sel=t,t)if("__custom__"===t)e.emb_custom=!0,e.emb_model="",e.emb_dims_auto=null;else{e.emb_custom=!1,e.emb_model=t;const n=this.findModelEntry(e.emb_type,t);e.emb_dims_auto=n?.dims??null,e.emb_custom_model="",e.emb_custom_dims="",e.emb_save_catalog=!1}else this.clearModelSelection(e)},effectiveModel:e=>e.emb_custom?e.emb_custom_model.trim():e.emb_model,effectiveDims(e){if(e.emb_custom){const t=Number(e.emb_custom_dims);return Number.isInteger(t)&&t>0?t:null}return e.emb_dims_auto??null},async maybeSaveToCatalog(e){if(!e.emb_custom||!e.emb_save_catalog)return!0;const t=e.emb_custom_model.trim(),n=Number(e.emb_custom_dims);if(!t||!n)return!0;try{await fetch(`${__ENV__.API}/embeddings/models`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:e.emb_type,model:t,dims:n})}),await this.loadModelCatalog()}catch{}return!0},async openRegisterModel(t){await e.$ok.shared.modal.open({owner:e,title:"Register Model",content:'<register-model-modal :modal="modal" :initial-provider="initialProvider" :on-done="onDone" />',context:e=>({modal:e,initialProvider:t?.emb_type??"",onDone:async()=>{await this.refreshCatalogState(t)}})})},async refreshCatalogState(e){await this.loadModelCatalog(),e&&("ollama"===(e?.emb_type??"")&&Array.isArray(this.liveOllamaModels)&&this.liveOllamaModels.length||e.emb_model_sel)&&this.reconcileModelSelection(e)},async openModelCatalog(t){await e.$ok.shared.modal.open({owner:e,title:"Model Catalog",content:'<embed-model-catalog :initialprovider="initialProvider" :compact="true" :onchanged="onChanged" />',context:()=>({initialProvider:t?.emb_type??"",onChanged:async()=>{await this.refreshCatalogState(t)}})})},pl:{name:"",source_type:"",field:"",field_mode:"custom",mode:"inline",emb_type:"",emb_model_sel:"",emb_model:"",emb_dims_auto:null,emb_custom:!1,emb_custom_model:"",emb_custom_dims:"",emb_save_catalog:!1,emb_config:{},w_concurrency:"1",w_poll_interval:"1000",algorithm:"flat",alg_config:{},prepare:"none",prepare_custom:"",chunk_strategy:"off",chunk_custom:"",chunk_size:"512",chunk_overlap:"64",chunk_store_text:!0},onPlSourceTypeChange(e){this.pl.source_type=e,this.pl.field="",this.pl.field_mode=this.defaultFieldMode(e),this.loadDeepForType(e)},setPlFieldMode(e){this.pl.field_mode=e,this.pl.field=""},idx:{name:"",source_type:"",embedder:"",storage_key:"",field:"",field_mode:"custom",dims:"",mode:"inline",job_type:""},onIdxSourceTypeChange(e){this.idx.source_type=e,this.idx.field="",this.idx.field_mode=this.defaultFieldMode(e),this.loadDeepForType(e)},setIdxFieldMode(e){this.idx.field_mode=e,this.idx.field=""},emb:{name:"",emb_type:"",emb_model_sel:"",emb_model:"",emb_dims_auto:null,emb_custom:!1,emb_custom_model:"",emb_custom_dims:"",emb_save_catalog:!1,emb_config:{}},srch:{name:"",source_type:"",storage_key:"",dims:"",embedder:"",algorithm:"flat",alg_config:{}},wkr:{name:"",job_type:"",indexer:"",embedder:"",concurrency:"1",pollInterval:"1000",ttl:"30000"},setTab(e){this.tab=e,this.error=null,this.success=null},num(e){const t=Number(e);return isNaN(t)||""===e?void 0:t},async submitPipeline(){const e=this.pl;if(!e.name.trim())return this.error="Name is required";if(!e.source_type.trim())return this.error="Source type is required";const t=this.effectiveModel(e),n=this.effectiveDims(e);if(!t)return this.error="Model is required";if(e.emb_custom&&!n)return this.error="Dims is required for custom models";for(const t of this.providerFields(e.emb_type))if(t.required&&!e.emb_config[t.key]?.toString().trim())return this.error=`${t.label} is required`;await this.maybeSaveToCatalog(e);const l=this.lockedEnv,i=e.source_type.trim(),o={name:e.name.trim(),field:e.field.trim()||void 0,dims:n??void 0,mode:e.mode,embedder:{type:e.emb_type,model:t||void 0,...this.buildProviderConfig(e)},algorithm:e.algorithm},a=this.buildAlgorithmConfig(e);if(Object.keys(a).length&&(o.algorithm_config=a),"queue"===e.mode&&(o.worker={concurrency:this.num(e.w_concurrency),pollInterval:this.num(e.w_poll_interval)}),e.field.trim()&&"none"!==e.prepare&&(o.prepare="custom"===e.prepare?e.prepare_custom.trim():e.prepare),e.field.trim()&&"off"!==e.chunk_strategy){const t="custom"===e.chunk_strategy?e.chunk_custom.trim():e.chunk_strategy;o.chunk={strategy:t,size:this.num(e.chunk_size)??512,overlap:"fixed"===e.chunk_strategy?this.num(e.chunk_overlap)??64:void 0,storeText:e.chunk_store_text},void 0===o.chunk.overlap&&delete o.chunk.overlap}await this._post(`/env/${encodeURIComponent(l)}/type/${encodeURIComponent(i)}/pipelines`,o)},async submitEmbedder(){const e=this.emb;if(!e.name.trim())return this.error="Name is required";const t=this.effectiveModel(e);if(!t)return this.error="Model is required";for(const t of this.providerFields(e.emb_type))if(t.required&&!e.emb_config[t.key]?.toString().trim())return this.error=`${t.label} is required`;await this.maybeSaveToCatalog(e);const n={name:e.name.trim(),type:e.emb_type,model:t||void 0,...this.buildProviderConfig(e)};await this._post("/embeddings/embedders",n)},async submitIndexer(){const e=this.idx;if(!e.name.trim())return this.error="Name is required";if(!e.source_type.trim())return this.error="Source type is required";if(!e.embedder.trim())return this.error="Embedder name is required";const t={name:e.name.trim(),source_env:this.lockedEnv,source_type:e.source_type.trim(),embedder:e.embedder.trim(),storage_key:e.storage_key.trim()||void 0,field:e.field.trim()||void 0,dims:this.num(e.dims),mode:e.mode,job_type:e.job_type.trim()||void 0};await this._post("/embeddings/indexers",t)},async submitSearch(){const e=this.srch;if(!e.name.trim())return this.error="Name is required";const t=(this.lockedType??e.source_type??"").trim();if(!t)return this.error="Source type is required";if(!e.storage_key.trim())return this.error="Storage key is required";const n={name:e.name.trim(),source_type:t,source_env:this.lockedEnv,storage_key:e.storage_key.trim(),dims:e.dims?Number(e.dims):void 0,embedder:e.embedder.trim()||void 0,algorithm:e.algorithm},l=this.buildAlgorithmConfig(e);Object.keys(l).length&&(n.algorithm_config=l),await this._post("/embeddings/search",n)},async submitWorker(){const e=this.wkr;if(!e.name.trim())return this.error="Name is required";if(!e.job_type.trim())return this.error="Job type is required";if(!e.indexer.trim())return this.error="Indexer name is required";if(!e.embedder.trim())return this.error="Embedder name is required";const t={name:e.name.trim(),job_type:e.job_type.trim(),indexer:e.indexer.trim(),embedder:e.embedder.trim(),concurrency:this.num(e.concurrency),pollInterval:this.num(e.pollInterval),ttl:this.num(e.ttl)};await this._post("/embeddings/workers",t)},async _post(t,n){this.busy=!0,this.error=null,this.success=null;try{const l=await fetch(`${__ENV__.API}${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),i=await l.json();if(!l.ok){const e=i?.error?.message||i?.message||`HTTP ${l.status}`;return void(this.error=e.includes("ENGINE_ALREADY_EXISTS")?`An engine named "${n.name}" already exists.`:e)}this.success=i.data,e.$ok.shared?.toast?.success?.("Created!"),e.$dispatch("created",i.data)}catch(e){this.error=e?.message||String(e)}finally{this.busy=!1}},handleSubmit(){switch(this.tab){case"pipeline":return this.submitPipeline();case"embedder":return this.submitEmbedder();case"indexer":return this.submitIndexer();case"search":return this.submitSearch();case"worker":return this.submitWorker()}}}),async init(e){await Promise.all([this.loadTypes(),this.loadModelCatalog(),this.loadProviders(),this.loadAlgorithms()]);const t=e.$attr.initialtab;t&&["pipeline","embedder","indexer","search","worker"].includes(t)&&(this.tab=t);const n=e.$attr.locktype;n&&(this.pl.source_type=n,this.pl.field_mode=this.defaultFieldMode(n),this.idx.source_type=n,this.idx.field_mode=this.defaultFieldMode(n),this.srch.source_type=n,this.loadDeepForType(n)),this.lockedStorageKey&&(this.srch.storage_key=this.lockedStorageKey),this.lockedEmbedder&&(this.srch.embedder=this.lockedEmbedder);const l=this.providers[0]?.key??"";for(const e of[this.pl,this.emb]){e.emb_type=l,e.emb_config={};for(const t of this.providerFields(l))void 0!==t.default&&(e.emb_config[t.key]=t.default);this.clearModelSelection(e)}"ollama"===l&&this.refreshOllamaModels(this.pl);for(const e of[this.pl,this.srch])for(const t of this.algorithmFields(e.algorithm))void 0!==t.default&&(e.alg_config[t.key]=t.default)},template:'\n<div style="display:flex; flex-direction:column; gap:0; width:min(700px, 78vw); max-height:76vh; min-height:0;">\n\n\n \x3c!-- Tab bar --\x3e\n <div class="tab-bar">\n <button :class="tab === \'pipeline\' ? \'tab tab--on\' : \'tab\'" @click="setTab(\'pipeline\')">Pipeline</button>\n <button :class="tab === \'embedder\' ? \'tab tab--on\' : \'tab\'" @click="setTab(\'embedder\')">Embedder</button>\n <button :class="tab === \'indexer\' ? \'tab tab--on\' : \'tab\'" @click="setTab(\'indexer\')">Indexer</button>\n <button :class="tab === \'search\' ? \'tab tab--on\' : \'tab\'" @click="setTab(\'search\')">Search</button>\n <button :class="tab === \'worker\' ? \'tab tab--on\' : \'tab\'" @click="setTab(\'worker\')">Worker</button>\n </div>\n\n <div style="overflow:auto; flex:1; min-height:0; padding-right:4px;">\n\n \x3c!-- ── Pipeline ──────────────────────────────────────────────────── --\x3e\n <if :="tab === \'pipeline\'">\n <div class="card">\n <div class="card-title">New Pipeline <span style="font-weight:400; opacity:.5; font-size:12px;">(creates embedder + indexer + search in one step)</span></div>\n <div class="form-grid">\n\n <div class="section-title">General</div>\n <span class="form-label">Name *</span>\n <input class="form-input" :value="pl.name" @input="pl.name = $el.value" placeholder="articles-body" />\n\n <span class="form-label">Source type *</span>\n <if :="!lockedType">\n <select class="form-select" :value="pl.source_type" @change="onPlSourceTypeChange($el.value)">\n <option value="">— select a type —</option>\n <each :of="types" let:item="t">\n <option :value="t">{{ t }}</option>\n </each>\n </select>\n </if>\n <if :="lockedType">\n <div class="form-input" style="background:color-mix(in srgb, var(--okdb-app-bg-deep) 33%, transparent); border-color:color-mix(in srgb, var(--okdb-accent) 27%, transparent); color:var(--okdb-accent); cursor:default;">{{ lockedType }}</div>\n </if>\n\n <span class="form-label">Field</span>\n <div>\n <div class="mode-pills" style="margin-bottom:5px;">\n <button :class="pl.field_mode === \'text\' ? \'mode-pill mode-pill--on\' : \'mode-pill\'" @click="setPlFieldMode(\'text\')">text</button>\n <button :class="pl.field_mode === \'all\' ? \'mode-pill mode-pill--on\' : \'mode-pill\'" @click="setPlFieldMode(\'all\')">all</button>\n <button :class="pl.field_mode === \'custom\' ? \'mode-pill mode-pill--on\' : \'mode-pill\'" @click="setPlFieldMode(\'custom\')">custom</button>\n </div>\n <if :="pl.source_type">\n <field-path-input\n :value="pl.field"\n :items="getFieldItems(pl.source_type, pl.field_mode)"\n :allow-custom="pl.field_mode === \'custom\'"\n placeholder="blank = whole record"\n @change="pl.field = $event.detail"\n />\n </if>\n <if :="!pl.source_type">\n <div style="font-size:11px; opacity:.45; font-style:italic;">Select a source type first.</div>\n </if>\n </div>\n\n <span class="form-label">Mode</span>\n <select class="form-select" :value="pl.mode" @change="pl.mode = $el.value">\n <option value="inline">inline — embed immediately (local/fast models)</option>\n <option value="queue">queue — async via worker (remote APIs, scale)</option>\n </select>\n\n <div class="section-title">Embedder</div>\n <span class="form-label">Provider</span>\n <select class="form-select" :value="pl.emb_type" @change="onProviderChange(pl, $el.value)">\n <each :of="providers" let:item="p">\n <option :value="p.key">{{ p.label }}</option>\n </each>\n </select>\n\n <span class="form-label">Model</span>\n <div>\n <div style="display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:5px; flex-wrap:wrap;">\n <span style="font-size:11px; opacity:.5;">Choose a known model or register a custom one inline.</span>\n <div style="display:flex; align-items:center; gap:6px; flex-wrap:wrap;">\n <button @click="openModelCatalog(pl)" style="font-size:11px; padding:2px 8px; border-color:color-mix(in srgb, var(--okdb-accent) 33%, transparent); color:var(--okdb-accent); background:color-mix(in srgb, var(--okdb-accent) 6%, transparent);">Browse catalog</button>\n <button @click="openRegisterModel(pl)" style="font-size:11px; padding:2px 8px; border-color:color-mix(in srgb, var(--okdb-purple) 33%, transparent); color:var(--okdb-purple); background:color-mix(in srgb, var(--okdb-purple) 6%, transparent);">+ Register model</button>\n </div>\n </div>\n <if :="pl.emb_type === \'ollama\'">\n <div style="display:flex; align-items:center; gap:8px; margin-bottom:5px; flex-wrap:wrap;">\n <button @click="refreshOllamaModels(pl)" :disabled="liveOllamaLoading" style="font-size:11px; padding:2px 8px;">{{ liveOllamaLoading ? \'…\' : \'↺ Refresh\' }}</button>\n <span style="font-size:11px; opacity:.55;">\n <if :="liveOllamaModels === null">○ catalog (not yet probed)</if>\n <if :="Array.isArray(liveOllamaModels) && liveOllamaModels.length">● live — {{ liveOllamaModels.length }} installed</if>\n <if :="Array.isArray(liveOllamaModels) && !liveOllamaModels.length && !liveOllamaError">○ catalog (none found on server)</if>\n </span>\n <if :="liveOllamaError && (!Array.isArray(liveOllamaModels) || !liveOllamaModels.length)">\n <span style="font-size:11px; color:var(--okdb-danger); max-width:260px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;" :title="liveOllamaError">⚠ {{ liveOllamaError }}</span>\n </if>\n </div>\n </if>\n <select class="form-select" :value="pl.emb_model_sel" @change="onModelSelChange(pl, $el.value)">\n <option value="">— Select model —</option>\n <each :of="modelsForProvider(pl.emb_type)" let:item="m">\n <option :value="m.model">{{ modelLabel(m) }}</option>\n </each>\n <option value="__custom__">── Custom model… ──</option>\n </select>\n <if :="!pl.emb_custom && pl.emb_dims_auto">\n <div style="margin-top:5px;">\n <span class="dims-badge">{{ pl.emb_dims_auto }} dims (auto)</span>\n </div>\n </if>\n <if :="pl.emb_custom">\n <div class="custom-model-box">\n <div class="row">\n <label>Model name</label>\n <input class="form-input" style="flex:1;" :value="pl.emb_custom_model" @input="pl.emb_custom_model = $el.value" placeholder="e.g. my-fine-tuned-embed" />\n </div>\n <div class="row">\n <label>Dims *</label>\n <input class="form-input" style="width:90px;" type="number" :value="pl.emb_custom_dims" @input="pl.emb_custom_dims = $el.value" placeholder="e.g. 768" min="1" />\n <span style="font-size:11px; opacity:.45; font-style:italic;">Leave blank to auto-probe on start</span>\n </div>\n <label class="save-to-catalog">\n <input type="checkbox" :checked="pl.emb_save_catalog" @change="pl.emb_save_catalog = $el.checked" />\n Save this model to the catalog for future use\n </label>\n </div>\n </if>\n </div>\n\n \x3c!-- Dynamic provider config fields --\x3e\n <each :of="providerFields(pl.emb_type)" let:item="f">\n <span class="form-label">{{ f.label }}{{ f.required ? \' *\' : \'\' }}</span>\n <div>\n <input\n :type="f.type === \'password\' ? \'password\' : f.type === \'number\' ? \'number\' : \'text\'"\n class="form-input"\n :value="pl.emb_config[f.key] ?? \'\'"\n @input="pl.emb_config[f.key] = $el.value"\n :placeholder="f.placeholder ?? \'\'"\n />\n <if :="f.hint">\n <div class="field-hint">{{ f.hint }}</div>\n </if>\n </div>\n </each>\n <if :="providerNote(pl.emb_type)">\n <span style="grid-column:1/-1; opacity:.5; font-style:italic; font-size:11px;">{{ providerNote(pl.emb_type) }}</span>\n </if>\n\n <if :="pl.mode === \'queue\'">\n <div class="section-title">Worker (queue mode)</div>\n <span class="form-label">Concurrency</span>\n <input class="form-input" type="number" :value="pl.w_concurrency" @input="pl.w_concurrency = $el.value" placeholder="1" min="1" />\n <span class="form-label">Poll interval (ms)</span>\n <input class="form-input" type="number" :value="pl.w_poll_interval" @input="pl.w_poll_interval = $el.value" placeholder="1000" min="100" />\n </if>\n\n \x3c!-- ── Prepare + Chunk (only relevant when a specific field is selected) ── --\x3e\n <if :="pl.field.trim()">\n <div class="section-title">Text Processing</div>\n\n <span class="form-label">Prepare</span>\n <div>\n <select class="form-select" :value="pl.prepare" @change="pl.prepare = $el.value">\n <option value="none">none — use field value as-is</option>\n <option value="html">html — strip tags, decode entities</option>\n <option value="markdown">markdown — strip syntax, keep text</option>\n <option value="json-text">json-text — extract string values from JSON</option>\n <option value="custom">custom — use a registered preparer</option>\n </select>\n <if :="pl.prepare === \'custom\'">\n <input class="form-input" style="margin-top:5px;" :value="pl.prepare_custom" @input="pl.prepare_custom = $el.value" placeholder="name passed to okdb.embeddings.registerPreparer()" />\n <div class="field-hint">Register server-side: <code>okdb.embeddings.registerPreparer(\'name\', fn)</code></div>\n </if>\n <if :="pl.prepare !== \'custom\'">\n <div class="field-hint">Cleans the field text before chunking and embedding.</div>\n </if>\n </div>\n\n <span class="form-label">Chunking</span>\n <div>\n <select class="form-select" :value="pl.chunk_strategy" @change="pl.chunk_strategy = $el.value">\n <option value="off">off — embed whole field as one vector</option>\n <option value="fixed">fixed — split by character count</option>\n <option value="sentence">sentence — split on sentence boundaries</option>\n <option value="paragraph">paragraph — split on paragraph breaks</option>\n <option value="custom">custom — use a registered strategy</option>\n </select>\n <if :="pl.chunk_strategy === \'custom\'">\n <input class="form-input" style="margin-top:5px;" :value="pl.chunk_custom" @input="pl.chunk_custom = $el.value" placeholder="name passed to okdb.embeddings.registerChunkStrategy()" />\n <div class="field-hint">Register server-side: <code>okdb.embeddings.registerChunkStrategy(\'name\', fn)</code></div>\n </if>\n <if :="pl.chunk_strategy !== \'off\'">\n <div style="display:grid; grid-template-columns:auto 1fr auto 1fr; gap:6px 8px; align-items:center; margin-top:8px; font-size:12px;">\n <span style="opacity:.6;">Size</span>\n <input class="form-input" type="number"\n :value="pl.chunk_size" @input="pl.chunk_size = $el.value"\n placeholder="512" min="32" style="width:80px;"\n title="Max characters per chunk" />\n <if :="pl.chunk_strategy === \'fixed\'">\n <span style="opacity:.6;">Overlap</span>\n <input class="form-input" type="number"\n :value="pl.chunk_overlap" @input="pl.chunk_overlap = $el.value"\n placeholder="64" min="0" style="width:80px;"\n title="Overlap characters between consecutive chunks" />\n </if>\n </div>\n <label style="display:flex; align-items:center; gap:6px; margin-top:8px; font-size:12px; cursor:pointer;">\n <input type="checkbox" :checked="pl.chunk_store_text" @change="pl.chunk_store_text = $el.checked" />\n <span>Store chunk text in doc_status <span style="opacity:.45;">(enables preview in search results)</span></span>\n </label>\n <div class="field-hint" style="margin-top:4px;">\n Each chunk is identified by a content hash — unchanged chunks are never re-embedded on update.\n </div>\n </if>\n </div>\n </if>\n <if :="!pl.field.trim()">\n <div class="section-title">Text Processing</div>\n <span style="grid-column:1/-1; font-size:11px; opacity:.4; font-style:italic;">\n Select a specific field above to enable prepare &amp; chunking options.\n </span>\n </if>\n\n <div class="section-title">Search Index</div>\n <span class="form-label">Algorithm</span>\n <div>\n <select class="form-select" :value="pl.algorithm" @change="onAlgorithmChange(pl, $el.value)">\n <each :of="algorithms" let:item="a">\n <option :value="a.key">{{ a.label }}</option>\n </each>\n </select>\n <if :="algorithmNote(pl.algorithm)">\n <div class="field-hint">{{ algorithmNote(pl.algorithm) }}</div>\n </if>\n </div>\n <each :of="algorithmFields(pl.algorithm)" let:item="f">\n <span class="form-label">{{ f.label }}</span>\n <div>\n <if :="f.type === \'select\'">\n <select class="form-select" :value="pl.alg_config[f.key] ?? \'\'" @change="pl.alg_config[f.key] = $el.value">\n <each :of="f.options ?? []" let:item="o">\n <option :value="o.value">{{ o.label }}</option>\n </each>\n </select>\n </if>\n <if :="f.type !== \'select\'">\n <input\n :type="f.type === \'number\' ? \'number\' : \'text\'"\n class="form-input"\n :value="pl.alg_config[f.key] ?? \'\'"\n @input="pl.alg_config[f.key] = $el.value"\n :placeholder="f.placeholder ?? \'\'"\n />\n </if>\n <if :="f.hint">\n <div class="field-hint">{{ f.hint }}</div>\n </if>\n </div>\n </each>\n\n\n </div>\n </div>\n </if>\n\n \x3c!-- ── Embedder ───────────────────────────────────────────────────── --\x3e\n <if :="tab === \'embedder\'">\n <div class="card">\n <div class="card-title">New Embedder</div>\n <div class="form-grid">\n <span class="form-label">Name *</span>\n <input class="form-input" :value="emb.name" @input="emb.name = $el.value" placeholder="my-ollama" />\n\n <span class="form-label">Provider</span>\n <select class="form-select" :value="emb.emb_type" @change="onProviderChange(emb, $el.value)">\n <each :of="providers" let:item="p">\n <option :value="p.key">{{ p.label }}</option>\n </each>\n </select>\n\n <span class="form-label">Model</span>\n <div>\n <div style="display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:5px; flex-wrap:wrap;">\n <span style="font-size:11px; opacity:.5;">Choose a known model or register a custom one inline.</span>\n <div style="display:flex; align-items:center; gap:6px; flex-wrap:wrap;">\n <button @click="openModelCatalog(emb)" style="font-size:11px; padding:2px 8px; border-color:color-mix(in srgb, var(--okdb-accent) 33%, transparent); color:var(--okdb-accent); background:color-mix(in srgb, var(--okdb-accent) 6%, transparent);">Browse catalog</button>\n <button @click="openRegisterModel(emb)" style="font-size:11px; padding:2px 8px; border-color:color-mix(in srgb, var(--okdb-purple) 33%, transparent); color:var(--okdb-purple); background:color-mix(in srgb, var(--okdb-purple) 6%, transparent);">+ Register model</button>\n </div>\n </div>\n <if :="emb.emb_type === \'ollama\'">\n <div style="display:flex; align-items:center; gap:8px; margin-bottom:5px; flex-wrap:wrap;">\n <button @click="refreshOllamaModels(emb)" :disabled="liveOllamaLoading" style="font-size:11px; padding:2px 8px;">{{ liveOllamaLoading ? \'…\' : \'↺ Refresh\' }}</button>\n <span style="font-size:11px; opacity:.55;">\n <if :="liveOllamaModels === null">○ catalog (not yet probed)</if>\n <if :="Array.isArray(liveOllamaModels) && liveOllamaModels.length">● live — {{ liveOllamaModels.length }} installed</if>\n <if :="Array.isArray(liveOllamaModels) && !liveOllamaModels.length && !liveOllamaError">○ catalog (none found on server)</if>\n </span>\n <if :="liveOllamaError && (!Array.isArray(liveOllamaModels) || !liveOllamaModels.length)">\n <span style="font-size:11px; color:var(--okdb-danger); max-width:260px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;" :title="liveOllamaError">⚠ {{ liveOllamaError }}</span>\n </if>\n </div>\n </if>\n <select class="form-select" :value="emb.emb_model_sel" @change="onModelSelChange(emb, $el.value)">\n <option value="">— Select model —</option>\n <each :of="modelsForProvider(emb.emb_type)" let:item="m">\n <option :value="m.model">{{ modelLabel(m) }}</option>\n </each>\n <option value="__custom__">── Custom model… ──</option>\n </select>\n <if :="!emb.emb_custom && emb.emb_dims_auto">\n <div style="margin-top:5px;">\n <span class="dims-badge">{{ emb.emb_dims_auto }} dims (auto)</span>\n </div>\n </if>\n <if :="emb.emb_custom">\n <div class="custom-model-box">\n <div class="row">\n <label>Model name</label>\n <input class="form-input" style="flex:1;" :value="emb.emb_custom_model" @input="emb.emb_custom_model = $el.value" placeholder="e.g. my-fine-tuned-embed" />\n </div>\n <div class="row">\n <label>Dims</label>\n <input class="form-input" style="width:90px;" type="number" :value="emb.emb_custom_dims" @input="emb.emb_custom_dims = $el.value" placeholder="auto" min="1" />\n <span style="font-size:11px; opacity:.45; font-style:italic;">Auto-probed on start if blank</span>\n </div>\n <label class="save-to-catalog">\n <input type="checkbox" :checked="emb.emb_save_catalog" @change="emb.emb_save_catalog = $el.checked" />\n Save this model to the catalog for future use\n </label>\n </div>\n </if>\n </div>\n\n \x3c!-- Dynamic provider config fields --\x3e\n <each :of="providerFields(emb.emb_type)" let:item="f">\n <span class="form-label">{{ f.label }}{{ f.required ? \' *\' : \'\' }}</span>\n <div>\n <input\n :type="f.type === \'password\' ? \'password\' : f.type === \'number\' ? \'number\' : \'text\'"\n class="form-input"\n :value="emb.emb_config[f.key] ?? \'\'"\n @input="emb.emb_config[f.key] = $el.value"\n :placeholder="f.placeholder ?? \'\'"\n />\n <if :="f.hint">\n <div class="field-hint">{{ f.hint }}</div>\n </if>\n </div>\n </each>\n <if :="providerNote(emb.emb_type)">\n <span style="grid-column:1/-1; opacity:.5; font-style:italic; font-size:11px;">{{ providerNote(emb.emb_type) }}</span>\n </if>\n\n </div>\n </div>\n </if>\n\n \x3c!-- ── Indexer ────────────────────────────────────────────────────── --\x3e\n <if :="tab === \'indexer\'">\n <div class="card">\n <div class="card-title">New Indexer</div>\n <div class="form-grid">\n <span class="form-label">Name *</span>\n <input class="form-input" :value="idx.name" @input="idx.name = $el.value" placeholder="articles-body" />\n\n <span class="form-label">Source type *</span>\n <if :="!lockedType">\n <select class="form-select" :value="idx.source_type" @change="onIdxSourceTypeChange($el.value)">\n <option value="">— select a type —</option>\n <each :of="types" let:item="t">\n <option :value="t">{{ t }}</option>\n </each>\n </select>\n </if>\n <if :="lockedType">\n <div class="form-input" style="background:color-mix(in srgb, var(--okdb-app-bg-deep) 33%, transparent); border-color:color-mix(in srgb, var(--okdb-accent) 27%, transparent); color:var(--okdb-accent); cursor:default;">{{ lockedType }}</div>\n </if>\n\n <span class="form-label">Embedder name *</span>\n <input class="form-input" :value="idx.embedder" @input="idx.embedder = $el.value" placeholder="my-ollama" />\n <span class="form-label">Storage key</span>\n <input class="form-input" :value="idx.storage_key" @input="idx.storage_key = $el.value" placeholder="same as name if blank" />\n\n <span class="form-label">Field</span>\n <div>\n <div class="mode-pills" style="margin-bottom:5px;">\n <button :class="idx.field_mode === \'text\' ? \'mode-pill mode-pill--on\' : \'mode-pill\'" @click="setIdxFieldMode(\'text\')">text</button>\n <button :class="idx.field_mode === \'all\' ? \'mode-pill mode-pill--on\' : \'mode-pill\'" @click="setIdxFieldMode(\'all\')">all</button>\n <button :class="idx.field_mode === \'custom\' ? \'mode-pill mode-pill--on\' : \'mode-pill\'" @click="setIdxFieldMode(\'custom\')">custom</button>\n </div>\n <if :="idx.source_type">\n <field-path-input\n :value="idx.field"\n :items="getFieldItems(idx.source_type, idx.field_mode)"\n :allow-custom="idx.field_mode === \'custom\'"\n placeholder="blank = whole record"\n @change="idx.field = $event.detail"\n />\n </if>\n <if :="!idx.source_type">\n <div style="font-size:11px; opacity:.45; font-style:italic;">Select a source type first.</div>\n </if>\n </div>\n\n <span class="form-label">Dims</span>\n <div>\n <input class="form-input" type="number" :value="idx.dims" @input="idx.dims = $el.value" placeholder="auto (from embedder)" />\n <div class="field-hint">Leave blank — inherited from the named embedder engine</div>\n </div>\n <span class="form-label">Mode</span>\n <select class="form-select" :value="idx.mode" @change="idx.mode = $el.value">\n <option value="inline">inline</option>\n <option value="queue">queue</option>\n </select>\n <if :="idx.mode === \'queue\'">\n <span class="form-label">Job type</span>\n <input class="form-input" :value="idx.job_type" @input="idx.job_type = $el.value" placeholder="embed:indexer@name (auto if blank)" />\n </if>\n </div>\n </div>\n </if>\n\n \x3c!-- ── Search ─────────────────────────────────────────────────────── --\x3e\n <if :="tab === \'search\'">\n <div class="card">\n <div class="card-title">New Vector Search Engine</div>\n <div class="form-grid">\n <span class="form-label">Name *</span>\n <div>\n <input class="form-input" :value="srch.name" @input="srch.name = $el.value" placeholder="default:articles-body-alt" />\n <div class="field-hint">Use a unique engine name. In env-scoped views, names are usually prefixed with the environment.</div>\n </div>\n <span class="form-label">Source type *</span>\n <if :="!lockedType">\n <select class="form-select" :value="srch.source_type" @change="srch.source_type = $el.value">\n <option value="">— select a type —</option>\n <each :of="types" let:item="t">\n <option :value="t">{{ t }}</option>\n </each>\n </select>\n </if>\n <if :="lockedType">\n <div class="form-input" style="background:color-mix(in srgb, var(--okdb-app-bg-deep) 33%, transparent); border-color:color-mix(in srgb, var(--okdb-accent) 27%, transparent); color:var(--okdb-accent); cursor:default;">{{ lockedType }}</div>\n </if>\n <span class="form-label">Storage key *</span>\n <if :="!lockedStorageKey">\n <input class="form-input" :value="srch.storage_key" @input="srch.storage_key = $el.value" placeholder="articles-body" />\n </if>\n <if :="lockedStorageKey">\n <div class="form-input" style="background:color-mix(in srgb, var(--okdb-app-bg-deep) 33%, transparent); border-color:color-mix(in srgb, var(--okdb-accent) 27%, transparent); color:var(--okdb-accent); cursor:default;">{{ lockedStorageKey }}</div>\n </if>\n <span class="form-label">Embedder name</span>\n <if :="!lockedEmbedder">\n <input class="form-input" :value="srch.embedder" @input="srch.embedder = $el.value" placeholder="my-ollama (enables text queries + auto dims)" />\n </if>\n <if :="lockedEmbedder">\n <div class="form-input" style="background:color-mix(in srgb, var(--okdb-app-bg-deep) 33%, transparent); border-color:color-mix(in srgb, var(--okdb-info) 27%, transparent); color:var(--okdb-info); cursor:default;">{{ lockedEmbedder }}</div>\n </if>\n <span class="form-label">Dims</span>\n <div>\n <input class="form-input" type="number" :value="srch.dims" @input="srch.dims = $el.value" placeholder="auto (from embedder)" min="1" />\n <div class="field-hint">Leave blank — resolved from the named embedder engine</div>\n </div>\n <span class="form-label">Algorithm</span>\n <div>\n <select class="form-select" :value="srch.algorithm" @change="onAlgorithmChange(srch, $el.value)">\n <each :of="algorithms" let:item="a">\n <option :value="a.key">{{ a.label }}</option>\n </each>\n </select>\n <if :="algorithmNote(srch.algorithm)">\n <div class="field-hint">{{ algorithmNote(srch.algorithm) }}</div>\n </if>\n </div>\n <each :of="algorithmFields(srch.algorithm)" let:item="f">\n <span class="form-label">{{ f.label }}</span>\n <div>\n <if :="f.type === \'select\'">\n <select class="form-select" :value="srch.alg_config[f.key] ?? \'\'" @change="srch.alg_config[f.key] = $el.value">\n <each :of="f.options ?? []" let:item="o">\n <option :value="o.value">{{ o.label }}</option>\n </each>\n </select>\n </if>\n <if :="f.type !== \'select\'">\n <input\n :type="f.type === \'number\' ? \'number\' : \'text\'"\n class="form-input"\n :value="srch.alg_config[f.key] ?? \'\'"\n @input="srch.alg_config[f.key] = $el.value"\n :placeholder="f.placeholder ?? \'\'"\n />\n </if>\n <if :="f.hint">\n <div class="field-hint">{{ f.hint }}</div>\n </if>\n </div>\n </each>\n </div>\n </div>\n </if>\n\n \x3c!-- ── Worker ─────────────────────────────────────────────────────── --\x3e\n <if :="tab === \'worker\'">\n <div class="card">\n <div class="card-title">New Embed Worker <span style="font-weight:400; opacity:.5; font-size:12px;">(queue mode only)</span></div>\n <div class="form-grid">\n <span class="form-label">Name *</span>\n <input class="form-input" :value="wkr.name" @input="wkr.name = $el.value" placeholder="articles-body-worker" />\n <span class="form-label">Job type *</span>\n <input class="form-input" :value="wkr.job_type" @input="wkr.job_type = $el.value" placeholder="embed:indexer@articles-body" />\n <span class="form-label hint">convention: embed:indexer@{indexer-name}</span><span></span>\n <span class="form-label">Indexer name *</span>\n <input class="form-input" :value="wkr.indexer" @input="wkr.indexer = $el.value" placeholder="articles-body" />\n <span class="form-label">Embedder name *</span>\n <input class="form-input" :value="wkr.embedder" @input="wkr.embedder = $el.value" placeholder="my-ollama" />\n <span class="form-label">Concurrency</span>\n <input class="form-input" type="number" :value="wkr.concurrency" @input="wkr.concurrency = $el.value" placeholder="1" min="1" />\n <span class="form-label">Poll interval (ms)</span>\n <input class="form-input" type="number" :value="wkr.pollInterval" @input="wkr.pollInterval = $el.value" placeholder="1000" min="100" />\n <span class="form-label">TTL (ms)</span>\n <input class="form-input" type="number" :value="wkr.ttl" @input="wkr.ttl = $el.value" placeholder="30000" min="1000" />\n </div>\n </div>\n </if>\n\n </div>\n\n \x3c!-- Footer bar --\x3e\n <div style="padding-top:14px; display:flex; align-items:center; gap:10px; flex-wrap:wrap;">\n <button\n @click="handleSubmit"\n :disabled="busy"\n style="background:color-mix(in srgb, var(--okdb-accent) 13%, transparent); border-color:var(--okdb-accent); color:var(--okdb-accent); font-weight:600; padding:7px 20px;"\n >\n {{ busy ? \'Creating…\' : \'Create\' }}\n </button>\n\n <if :="error">\n <div class="error-box">{{ error }}</div>\n </if>\n\n <if :="success && !error">\n <span style="color:var(--okdb-success); font-size:13px;">✓ Created successfully</span>\n </if>\n </div>\n\n</div>\n',style:"\n .card { background:var(--okdb-app-surface); border-radius:12px; padding:16px; box-shadow:0 0 5px #ffffff1a; }\n .card-title { font-weight:600; margin-bottom:12px; font-size:14px; }\n .form-grid { display:grid; grid-template-columns:140px 1fr; gap:8px 12px; align-items:center; font-size:13px; }\n .form-label { opacity:.7; text-align:right; }\n .form-input { background:var(--okdb-app-bg-deep); border:1px solid var(--okdb-app-border); border-radius:6px; padding:6px 8px; color:inherit; font-size:13px; width:100%; box-sizing:border-box; }\n .form-input:focus { outline:none; border-color:var(--okdb-accent); }\n .form-select { background:var(--okdb-app-bg-deep); border:1px solid var(--okdb-app-border); border-radius:6px; padding:6px 8px; color:inherit; font-size:13px; width:100%; box-sizing:border-box; }\n .tab-bar { display:flex; gap:2px; border-bottom:1px solid var(--okdb-app-border); margin-bottom:16px; }\n .tab { padding:7px 14px; border-radius:6px 6px 0 0; cursor:pointer; font-size:13px; border:1px solid transparent; border-bottom:none; background:transparent; }\n .tab:hover { background:var(--okdb-app-surface); }\n .tab--on { background:var(--okdb-app-surface); border-color:var(--okdb-app-border); color:var(--okdb-accent); }\n .section-title { font-size:11px; text-transform:uppercase; opacity:.45; letter-spacing:.06em; margin:14px 0 6px; grid-column:1/-1; }\n .hint { font-size:11px; opacity:.5; font-style:italic; }\n .error-box { color:var(--okdb-danger); font-size:13px; padding:8px 12px; border:1px solid var(--okdb-danger); border-radius:6px; }\n .mode-pills { display:flex; gap:3px; }\n .mode-pill { padding:2px 8px; border-radius:999px; font-size:11px; border:1px solid var(--okdb-app-border); background:transparent; cursor:pointer; color:inherit; opacity:.7; }\n .mode-pill:hover { opacity:1; border-color:color-mix(in srgb, var(--okdb-accent) 27%, transparent); }\n .mode-pill--on { border-color:var(--okdb-accent); color:var(--okdb-accent); opacity:1; background:color-mix(in srgb, var(--okdb-accent) 7%, transparent); }\n .field-hint { font-size:11px; opacity:.45; font-style:italic; margin-top:2px; grid-column:2; }\n .dims-badge { display:inline-flex; align-items:center; gap:6px; font-size:12px; color:var(--okdb-accent); background:color-mix(in srgb, var(--okdb-accent) 7%, transparent); border:1px solid color-mix(in srgb, var(--okdb-accent) 27%, transparent); border-radius:6px; padding:3px 10px; }\n .dims-badge-muted { color:#888; border-color:var(--okdb-app-border); background:transparent; }\n .custom-model-box { background:var(--okdb-app-bg-deep); border:1px solid var(--okdb-app-border); border-radius:8px; padding:10px 12px; margin-top:4px; display:flex; flex-direction:column; gap:8px; }\n .custom-model-box .row { display:flex; gap:8px; align-items:center; }\n .custom-model-box label { font-size:12px; opacity:.6; white-space:nowrap; }\n .save-to-catalog { display:flex; align-items:center; gap:6px; font-size:12px; opacity:.7; cursor:pointer; }\n .save-to-catalog input { cursor:pointer; }\n"};
@@ -1 +1 @@
1
- const _0x5ae01f=_0x5ba6;(function(_0x218c85,_0x67a654){const _0x2dd9bc=_0x5ba6,_0x1f5f67=_0x218c85();while(!![]){try{const _0x1b1088=parseInt(_0x2dd9bc(0x1c5))/0x1*(-parseInt(_0x2dd9bc(0x1b7))/0x2)+parseInt(_0x2dd9bc(0x1c7))/0x3+parseInt(_0x2dd9bc(0x1c3))/0x4+-parseInt(_0x2dd9bc(0x1c0))/0x5*(-parseInt(_0x2dd9bc(0x1ce))/0x6)+parseInt(_0x2dd9bc(0x1c1))/0x7*(parseInt(_0x2dd9bc(0x1ae))/0x8)+-parseInt(_0x2dd9bc(0x1d0))/0x9*(-parseInt(_0x2dd9bc(0x1b0))/0xa)+parseInt(_0x2dd9bc(0x1b8))/0xb*(-parseInt(_0x2dd9bc(0x1c9))/0xc);if(_0x1b1088===_0x67a654)break;else _0x1f5f67['push'](_0x1f5f67['shift']());}catch(_0x47c734){_0x1f5f67['push'](_0x1f5f67['shift']());}}}(_0x2195,0x3f74d));import _0x12b764 from'../../engines/parts/engine-panel-shell.ok.js';import{ENGINE_PANEL_SHARED_STYLE as _0x105abf}from'../../engines/engine-panel-shared-style.js';import{dispatchEnginePipelineSelection as _0x269c4e,maskSensitiveConfig as _0x14628d}from'../../engines/engine-ui-utils.js';const s=_0x105abf;function _0x2195(){const _0x20b69a=['5121XGSeJq','error','fmtConfig','eng','81976dEyhXl','API','7770OzoGZj','type','config','checkHealth','/health','$attr','isRunning','2znyCzT','185834HEabGR','filter','busy','message','entries','/embeddings/embedders/','model','engine','10UDDIQj','21DPcowl','$watch','1830732ikuHHk','includes','493231vGEwsU','latency','1216797zXlFbe','data','780iolRBi','name','dims','health','health\x20check\x20failed','1545366FNdGOF','\x0a<engine-panel-shell\x0a\x20\x20:engine=\x22eng\x22\x0a\x20\x20:title=\x22name\x22\x0a\x20\x20type-label=\x22embedder\x22\x0a\x20\x20type-color=\x22var(--okdb-info)\x22\x0a\x20\x20show-refresh=\x22true\x22\x0a\x20\x20:refresh-busy=\x22busy\x22\x0a\x20\x20:on-refresh=\x22reloadPanel\x22\x0a\x20\x20:on-pipeline=\x22viewPipeline\x22\x0a\x20\x20@engine-updated=\x22$dispatch(\x27engine-updated\x27,\x20$event.detail)\x22\x0a\x20\x20@refresh=\x22$dispatch(\x27refresh\x27)\x22\x0a\x20\x20@deleted=\x22$dispatch(\x27deleted\x27,\x20$event.detail)\x22\x0a>\x0a\x20\x20<div\x20class=\x22stack-compact\x22>\x0a\x20\x20\x20\x20<div\x20class=\x22card\x20stack-compact\x22\x20style=\x22padding:14px;gap:12px;\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:8px;min-width:0;flex:1;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22pill-row\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22info-pill\x22\x20title=\x22Embedding\x20provider\x20type.\x22>{{\x20providerType\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22info-pill\x22\x20title=\x22Active\x20model.\x22>{{\x20modelName\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22health?.ok\x20===\x20true\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22info-pill\x22\x20style=\x22border-color:color-mix(in\x20srgb,\x20var(--okdb-success)\x2033%,\x20transparent);color:var(--okdb-success);background:color-mix(in\x20srgb,\x20var(--okdb-success)\x207%,\x20transparent);\x22>healthy</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22health?.ok\x20===\x20false\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22info-pill\x22\x20style=\x22border-color:color-mix(in\x20srgb,\x20var(--okdb-danger)\x2033%,\x20transparent);color:var(--okdb-danger);background:color-mix(in\x20srgb,\x20var(--okdb-danger)\x207%,\x20transparent);\x22>unhealthy</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22story-lead\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Live\x20embedding\x20connection\x20for\x20<strong>{{\x20modelName\x20}}</strong>\x20on\x20<strong>{{\x20providerType\x20}}</strong>.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Indexers\x20and\x20workers\x20depend\x20on\x20this\x20engine\x20to\x20turn\x20content\x20into\x20vectors.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22story-note\x22>Use\x20health\x20checks\x20to\x20confirm\x20the\x20provider\x20is\x20reachable\x20and\x20returning\x20the\x20expected\x20vector\x20shape\x20before\x20debugging\x20downstream\x20pipelines.</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22metric-grid\x20metric-grid--compact\x22\x20style=\x22min-width:min(100%,\x20340px);\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22metric-card\x20metric-card--compact\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22metric-title\x22>Dims</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22metric-value\x22\x20style=\x22color:var(--okdb-accent);\x22>{{\x20dimsValue\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22metric-card\x20metric-card--compact\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22metric-title\x22>Latency</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22metric-value\x22\x20style=\x22color:var(--okdb-app-fg);\x22>{{\x20latencyValue\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:10px;flex-wrap:wrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22checkHealth\x22\x20:disabled=\x22busy\x20||\x20!eng.isRunning\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{{\x20busy\x20?\x20\x27Checking…\x27\x20:\x20\x27Check\x20Health\x27\x20}}\x0a\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!eng.isRunning\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22story-note\x22>Start\x20the\x20engine\x20to\x20run\x20a\x20live\x20health\x20probe.</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22error\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22alert\x20alert--error\x22>{{\x20error\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20<div\x20class=\x22card\x20stack-compact\x22\x20style=\x22padding:14px;gap:12px;\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22card-title\x22\x20style=\x22margin:0;\x22>Connection\x20details</div>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22kv-grid\x20kv-grid--compact\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22kv-key\x22>provider</span><span\x20class=\x22kv-val\x22>{{\x20providerType\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22kv-key\x22>model</span><span\x20class=\x22kv-val\x22>{{\x20modelName\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22kv-key\x22>dims</span><span\x20class=\x22kv-val\x22>{{\x20dimsValue\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22health\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22kv-key\x22>health</span><span\x20:style=\x22\x27color:\x27\x20+\x20(health.ok\x20?\x20\x27var(--okdb-success)\x27\x20:\x20\x27var(--okdb-danger)\x27)\x22>{{\x20health.ok\x20?\x20\x27ok\x27\x20:\x20\x27error\x27\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22configEntries.length\x20>\x200\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22kv-grid\x20kv-grid--compact\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22configEntries\x22\x20let:item=\x22pair\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22kv-key\x22>{{\x20pair[0]\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22kv-val\x22>{{\x20pair[1]\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20</div>\x0a\x20\x20</div>\x0a</engine-panel-shell>\x0a'];_0x2195=function(){return _0x20b69a;};return _0x2195();}function _0x5ba6(_0xc4b18f,_0x4de371){_0xc4b18f=_0xc4b18f-0x1ad;const _0x2195b8=_0x2195();let _0x5ba636=_0x2195b8[_0xc4b18f];return _0x5ba636;}export default{'tag':'embed-embedder-panel','dependencies':[_0x12b764],'attr':{'name':{},'engine':{}},'context':_0x48ed67=>({'busy':!0x1,'health':null,'error':null,get 'eng'(){const _0x1e13a0=_0x5ba6;return _0x48ed67[_0x1e13a0(0x1b5)][_0x1e13a0(0x1bf)]??{};},get 'name'(){const _0x415130=_0x5ba6;return _0x48ed67[_0x415130(0x1b5)]['name'];},get 'config'(){const _0x4a214d=_0x5ba6;return this['eng'][_0x4a214d(0x1b2)]??{};},get 'providerType'(){const _0xd31223=_0x5ba6;return this[_0xd31223(0x1cc)]?.[_0xd31223(0x1b1)]||this[_0xd31223(0x1b2)][_0xd31223(0x1b1)]||'—';},get 'modelName'(){const _0x5d8063=_0x5ba6;return this[_0x5d8063(0x1cc)]?.[_0x5d8063(0x1be)]||this[_0x5d8063(0x1b2)][_0x5d8063(0x1be)]||'—';},get 'dimsValue'(){const _0x23358c=_0x5ba6;return this[_0x23358c(0x1cc)]?.[_0x23358c(0x1cb)]??this['config']['dimensions']??'—';},get 'latencyValue'(){const _0x168361=_0x5ba6;return null!=this[_0x168361(0x1cc)]?.[_0x168361(0x1c6)]?this[_0x168361(0x1cc)][_0x168361(0x1c6)]+'ms':'—';},get 'configEntries'(){const _0x34a366=_0x5ba6;return Object[_0x34a366(0x1bc)](this[_0x34a366(0x1d2)](this[_0x34a366(0x1b2)]))[_0x34a366(0x1b9)](([_0x55dad7])=>![_0x34a366(0x1b1),_0x34a366(0x1be)][_0x34a366(0x1c4)](_0x55dad7));},async 'checkHealth'(){const _0x54fe9c=_0x5ba6;this[_0x54fe9c(0x1ba)]=!0x0,this[_0x54fe9c(0x1d1)]=null;try{const _0xf89f7a=await fetch(__ENV__[_0x54fe9c(0x1af)]+_0x54fe9c(0x1bd)+encodeURIComponent(this['name'])+_0x54fe9c(0x1b4)),_0x1c531e=await _0xf89f7a['json']();if(!_0xf89f7a['ok'])throw new Error(_0x1c531e?.[_0x54fe9c(0x1d1)]?.[_0x54fe9c(0x1bb)]||_0x54fe9c(0x1cd));this[_0x54fe9c(0x1cc)]=_0x1c531e[_0x54fe9c(0x1c8)];}catch(_0x22ecf9){this[_0x54fe9c(0x1d1)]=_0x22ecf9?.[_0x54fe9c(0x1bb)]||String(_0x22ecf9),this[_0x54fe9c(0x1cc)]=null;}finally{this[_0x54fe9c(0x1ba)]=!0x1;}},'fmtConfig':_0x14628d,'viewPipeline'(){_0x269c4e(_0x48ed67,this['eng']);},async 'reloadPanel'(){const _0x4f72af=_0x5ba6;this[_0x4f72af(0x1cc)]=null,this[_0x4f72af(0x1d1)]=null,this['eng'][_0x4f72af(0x1b6)]&&await this[_0x4f72af(0x1b3)]();}}),async 'init'(_0x3f0f3d){const _0x4eb6d9=_0x5ba6;_0x3f0f3d[_0x4eb6d9(0x1c2)](()=>_0x3f0f3d['$attr'][_0x4eb6d9(0x1ca)],async()=>{const _0xa4db3c=_0x4eb6d9;this['health']=null,this[_0xa4db3c(0x1d1)]=null,this[_0xa4db3c(0x1ad)][_0xa4db3c(0x1b6)]&&await this['checkHealth']();}),this[_0x4eb6d9(0x1ad)][_0x4eb6d9(0x1b6)]&&await this[_0x4eb6d9(0x1b3)]();},'template':_0x5ae01f(0x1cf),'style':s};
1
+ import e from"../../engines/parts/engine-panel-shell.ok.js";import{ENGINE_PANEL_SHARED_STYLE as n}from"../../engines/engine-panel-shared-style.js";import{dispatchEnginePipelineSelection as i,maskSensitiveConfig as t}from"../../engines/engine-ui-utils.js";const s=n;export default{tag:"embed-embedder-panel",dependencies:[e],attr:{name:{},engine:{}},context:e=>({busy:!1,health:null,error:null,get eng(){return e.$attr.engine??{}},get name(){return e.$attr.name},get config(){return this.eng.config??{}},get providerType(){return this.health?.type||this.config.type||"—"},get modelName(){return this.health?.model||this.config.model||"—"},get dimsValue(){return this.health?.dims??this.config.dimensions??"—"},get latencyValue(){return null!=this.health?.latency?`${this.health.latency}ms`:"—"},get configEntries(){return Object.entries(this.fmtConfig(this.config)).filter(([e])=>!["type","model"].includes(e))},async checkHealth(){this.busy=!0,this.error=null;try{const e=await fetch(`${__ENV__.API}/embeddings/embedders/${encodeURIComponent(this.name)}/health`),n=await e.json();if(!e.ok)throw new Error(n?.error?.message||"health check failed");this.health=n.data}catch(e){this.error=e?.message||String(e),this.health=null}finally{this.busy=!1}},fmtConfig:t,viewPipeline(){i(e,this.eng)},async reloadPanel(){this.health=null,this.error=null,this.eng.isRunning&&await this.checkHealth()}}),async init(e){e.$watch(()=>e.$attr.name,async()=>{this.health=null,this.error=null,this.eng.isRunning&&await this.checkHealth()}),this.eng.isRunning&&await this.checkHealth()},template:'\n<engine-panel-shell\n :engine="eng"\n :title="name"\n type-label="embedder"\n type-color="var(--okdb-info)"\n show-refresh="true"\n :refresh-busy="busy"\n :on-refresh="reloadPanel"\n :on-pipeline="viewPipeline"\n @engine-updated="$dispatch(\'engine-updated\', $event.detail)"\n @refresh="$dispatch(\'refresh\')"\n @deleted="$dispatch(\'deleted\', $event.detail)"\n>\n <div class="stack-compact">\n <div class="card stack-compact" style="padding:14px;gap:12px;">\n <div style="display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;">\n <div style="display:flex;flex-direction:column;gap:8px;min-width:0;flex:1;">\n <div class="pill-row">\n <span class="info-pill" title="Embedding provider type.">{{ providerType }}</span>\n <span class="info-pill" title="Active model.">{{ modelName }}</span>\n <if :="health?.ok === true">\n <span class="info-pill" style="border-color:color-mix(in srgb, var(--okdb-success) 33%, transparent);color:var(--okdb-success);background:color-mix(in srgb, var(--okdb-success) 7%, transparent);">healthy</span>\n </if>\n <if :="health?.ok === false">\n <span class="info-pill" style="border-color:color-mix(in srgb, var(--okdb-danger) 33%, transparent);color:var(--okdb-danger);background:color-mix(in srgb, var(--okdb-danger) 7%, transparent);">unhealthy</span>\n </if>\n </div>\n <div class="story-lead">\n Live embedding connection for <strong>{{ modelName }}</strong> on <strong>{{ providerType }}</strong>.\n Indexers and workers depend on this engine to turn content into vectors.\n </div>\n <div class="story-note">Use health checks to confirm the provider is reachable and returning the expected vector shape before debugging downstream pipelines.</div>\n </div>\n\n <div class="metric-grid metric-grid--compact" style="min-width:min(100%, 340px);">\n <div class="metric-card metric-card--compact">\n <div class="metric-title">Dims</div>\n <div class="metric-value" style="color:var(--okdb-accent);">{{ dimsValue }}</div>\n </div>\n <div class="metric-card metric-card--compact">\n <div class="metric-title">Latency</div>\n <div class="metric-value" style="color:var(--okdb-app-fg);">{{ latencyValue }}</div>\n </div>\n </div>\n </div>\n\n <div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;">\n <button @click="checkHealth" :disabled="busy || !eng.isRunning">\n {{ busy ? \'Checking…\' : \'Check Health\' }}\n </button>\n <if :="!eng.isRunning">\n <span class="story-note">Start the engine to run a live health probe.</span>\n </if>\n </div>\n\n <if :="error">\n <div class="alert alert--error">{{ error }}</div>\n </if>\n </div>\n\n <div class="card stack-compact" style="padding:14px;gap:12px;">\n <div class="card-title" style="margin:0;">Connection details</div>\n <div class="kv-grid kv-grid--compact">\n <span class="kv-key">provider</span><span class="kv-val">{{ providerType }}</span>\n <span class="kv-key">model</span><span class="kv-val">{{ modelName }}</span>\n <span class="kv-key">dims</span><span class="kv-val">{{ dimsValue }}</span>\n <if :="health">\n <span class="kv-key">health</span><span :style="\'color:\' + (health.ok ? \'var(--okdb-success)\' : \'var(--okdb-danger)\')">{{ health.ok ? \'ok\' : \'error\' }}</span>\n </if>\n </div>\n <if :="configEntries.length > 0">\n <div class="kv-grid kv-grid--compact">\n <each :of="configEntries" let:item="pair">\n <span class="kv-key">{{ pair[0] }}</span>\n <span class="kv-val">{{ pair[1] }}</span>\n </each>\n </div>\n </if>\n </div>\n </div>\n</engine-panel-shell>\n',style:s};
@@ -1 +1 @@
1
- var _0x220fa0=_0x4a6a;function _0x572b(){var _0x1d7b39=['401417cOCiyb','721NzzkjO','embed-engine-declaration-editor','9OfivtO','55079695xECPUy','765395DgjVbI','2457970YICqsy','6nVnLpi','2157231Gowbdz','118840qpjlFI','4168020XglyCC','4GhGoly'];_0x572b=function(){return _0x1d7b39;};return _0x572b();}function _0x4a6a(_0x2cadcf,_0x56c1fe){_0x2cadcf=_0x2cadcf-0xb4;var _0x572b8f=_0x572b();var _0x4a6a0c=_0x572b8f[_0x2cadcf];return _0x4a6a0c;}(function(_0x54bb65,_0x310393){var _0x5761c6=_0x4a6a,_0x377168=_0x54bb65();while(!![]){try{var _0x23e7bc=parseInt(_0x5761c6(0xbc))/0x1*(-parseInt(_0x5761c6(0xb7))/0x2)+-parseInt(_0x5761c6(0xb8))/0x3*(parseInt(_0x5761c6(0xbb))/0x4)+-parseInt(_0x5761c6(0xb5))/0x5+-parseInt(_0x5761c6(0xba))/0x6+-parseInt(_0x5761c6(0xbd))/0x7*(parseInt(_0x5761c6(0xb9))/0x8)+parseInt(_0x5761c6(0xbf))/0x9*(parseInt(_0x5761c6(0xb6))/0xa)+parseInt(_0x5761c6(0xb4))/0xb;if(_0x23e7bc===_0x310393)break;else _0x377168['push'](_0x377168['shift']());}catch(_0x5c589b){_0x377168['push'](_0x377168['shift']());}}}(_0x572b,0xe865c));import _0x53ba5f from'../../engines/parts/engine-declaration-editor.ok.js';export default{..._0x53ba5f,'tag':_0x220fa0(0xbe)};
1
+ import e from"../../engines/parts/engine-declaration-editor.ok.js";export default{...e,tag:"embed-engine-declaration-editor"};