@rubytech/create-maxy-code 0.1.427 → 0.1.429
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/embed-client/dist/index.d.ts +5 -1
- package/payload/platform/lib/embed-client/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/embed-client/dist/index.js +114 -36
- package/payload/platform/lib/embed-client/dist/index.js.map +1 -1
- package/payload/platform/lib/embed-client/src/index.ts +141 -34
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +4 -2
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -0
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-throughput.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-throughput.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-throughput.test.js +92 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-throughput.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-timeout.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-timeout.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-timeout.test.js +56 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-timeout.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js +56 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/lib/embeddings.d.ts +9 -3
- package/payload/platform/plugins/work/mcp/dist/lib/embeddings.d.ts.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/lib/embeddings.js +19 -15
- package/payload/platform/plugins/work/mcp/dist/lib/embeddings.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/embeddings.d.ts +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/embeddings.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/embeddings.js +7 -18
- package/payload/platform/plugins/workflows/mcp/dist/lib/embeddings.js.map +1 -1
- package/payload/server/{chunk-3Z5WE53X.js → chunk-UUG6ZSO5.js} +65 -9
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/AdminLoginScreens-C4AZT7cQ.js +1 -0
- package/payload/server/public/assets/AdminShell-BfLQQ27Z.js +2 -0
- package/payload/server/public/assets/{Checkbox-B_lfjsqd.js → Checkbox-BC0c_gbn.js} +1 -1
- package/payload/server/public/assets/admin-SaF1F4e-.js +1 -0
- package/payload/server/public/assets/{arc-dVLpR-ec.js → arc-qKfXIt8v.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-FPHT7s-C.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-C6u_CVzb.js → architectureDiagram-Q4EWVU46-DkVrGn7G.js} +1 -1
- package/payload/server/public/assets/audio-attachment-mime-BBW07eyG.js +2 -0
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Cy8F5b8O.js → blockDiagram-DXYQGD6D-DqavswGH.js} +1 -1
- package/payload/server/public/assets/{browser-CCWufeXr.js → browser-CvZxNdKw.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DRXrlepj.js → c4Diagram-AHTNJAMY-B7fyKiXe.js} +1 -1
- package/payload/server/public/assets/calendar-DXxLMF2J.js +1 -0
- package/payload/server/public/assets/channel-j70eMvcL.js +1 -0
- package/payload/server/public/assets/chat-B9Qjt7C9.js +1 -0
- package/payload/server/public/assets/chevron-left-CLPxfjDV.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-fEyfhRLz.js → chunk-2KRD3SAO-DsgMtGkv.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-NUWO4y7q.js → chunk-336JU56O-CkdISfNt.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-D-NcAlTW.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-BnfiNR3l.js → chunk-4BX2VUAB-CYpiF2bl.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-Bj_aJOz8.js → chunk-4TB4RGXK-CWyc_F7v.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-aK0DNSKb.js → chunk-55IACEB6-BbzKMw2Z.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-DeqAkq5C.js → chunk-5FUZZQ4R-u19Nai9e.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-SShlujAQ.js → chunk-5PVQY5BW-Ba8by6Uy.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-CZpzQ0DL.js → chunk-67CJDMHE-BwUuxtyb.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-COnjO6jy.js → chunk-7N4EOEYR-BRH9iM9L.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-C9V31L2z.js → chunk-AA7GKIK3-BGoztgLL.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-DSwnSGe3.js → chunk-BSJP7CBP-C5GDAZTl.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-CnRUTuta.js → chunk-CIAEETIT-ChY32VPS.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-BexiL2LH.js → chunk-EDXVE4YY-CPSD3p6p.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-aTklWdJQ.js → chunk-ENJZ2VHE-D1oL-iUr.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-svcEBQzs.js → chunk-FMBD7UC4-CPvYEr54.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-CG7R7Xri.js → chunk-FOC6F5B3-9Yyj7Vbz.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-CGN7Z4x9.js → chunk-ICPOFSXX-BaYgh8FR.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-CWBh78jw.js → chunk-K5T4RW27-5ucpeRvm.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-Ctiq4q-5.js → chunk-KGLVRYIC-DW-FHk7T.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-BII77Q7K.js → chunk-LIHQZDEY-CGGVfAyG.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-DT7R01H8.js → chunk-ORNJ4GCN-Bv8EUa5d.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-y-Jkbd4C.js → chunk-OYMX7WX6-C1mXJnyw.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-CAwbQBtf.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-DzFo6KbQ.js → chunk-U2HBQHQK-PwSQz6EP.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-CYSwgtLV.js → chunk-X2U36JSP--NPHTBlU.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-DHlM4tOn.js → chunk-XPW4576I-Bbc7Da32.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-B20rTmLl.js → chunk-YZCP3GAM-D-9v8e--.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-C7hP4J8m.js → chunk-ZZ45TVLE-CMPg670Q.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Ct6Rn0vt.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B_2XCIFv.js +1 -0
- package/payload/server/public/assets/clone-DjPWA_NH.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-nKjTv9sR.js → cose-bilkent-S5V4N54A-NVSb1Bhy.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-BNJYTnls.js → dagre-KV5264BT-V2Ai1DFl.js} +1 -1
- package/payload/server/public/assets/{dagre-Cx8LiiUZ.js → dagre-QfLcO-1j.js} +1 -1
- package/payload/server/public/assets/data-BKE6Sa-g.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-CoAN5_f9.js → diagram-5BDNPKRD-Caw21693.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-pRmsN4_x.js → diagram-G4DWMVQ6-CgwVkT2q.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-CRoylyp4.js → diagram-MMDJMWI5-DFUrLZhs.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-BT3ZtG5b.js → diagram-TYMM5635-CEEiEuZJ.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-DSKws1ZV.js → erDiagram-SMLLAGMA-CG10NrT3.js} +1 -1
- package/payload/server/public/assets/file-download-B2B2DTar.js +1 -0
- package/payload/server/public/assets/{flatten-jn8bZgcI.js → flatten-DAO0sfCM.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-C2L38ZE5.js → flowDiagram-DWJPFMVM-BqkV9Okv.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-Bm2h-vjm.js → ganttDiagram-T4ZO3ILL-DRiCDQF6.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-B8Hx7f-D.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BoowbF7u.js → gitGraphDiagram-UUTBAWPF-BZV2voyy.js} +1 -1
- package/payload/server/public/assets/graph-DRNzDBTV.js +51 -0
- package/payload/server/public/assets/{graph-labels-BLx-0vyT.js → graph-labels-DxqDdO7G.js} +1 -1
- package/payload/server/public/assets/{graphlib-BvT2s_o1.js → graphlib-DGPThX8M.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-BicCJTqU.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-tf-8rOez.js +2 -0
- package/payload/server/public/assets/{isEmpty-Dkk6_L-B.js → isEmpty-Cb_U81C6.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-nxcmj-IX.js → ishikawaDiagram-UXIWVN3A-BKsAxSvp.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-q5SNIvmS.js → journeyDiagram-VCZTEJTY-CmliuOd-.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-BugG9Q1o.js → kanban-definition-6JOO6SKY-DAlElMb-.js} +1 -1
- package/payload/server/public/assets/{line-MZCQLR-q.js → line-DKZqLKAC.js} +1 -1
- package/payload/server/public/assets/{linear-DmQGNk-g.js → linear-CbSGdh1x.js} +1 -1
- package/payload/server/public/assets/{maximize-2-CnNQnj_v.js → maximize-2-DKx6OBKv.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-DvoeqLxw.js → mermaid-parser.core-DFvbao9C.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-BLaw7iG4.js → mermaid.core-C0vEBxDm.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DMkt10Vc.js → mindmap-definition-QFDTVHPH-CShASUKd.js} +1 -1
- package/payload/server/public/assets/operator-CTJjI8te.js +1 -0
- package/payload/server/public/assets/{ordinal-DuJYM7p1.js → ordinal-H0tVmBDP.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +1 -0
- package/payload/server/public/assets/page-CbI1wtef.js +1 -0
- package/payload/server/public/assets/page-JzxyFGle.js +32 -0
- package/payload/server/public/assets/{pdf-render-riHufgrn.js → pdf-render-jAQU0nXt.js} +1 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-DzlGQW3J.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-DRp4lD2B.js → pieDiagram-DEJITSTG-CBZHpDAJ.js} +1 -1
- package/payload/server/public/assets/{play-yEkd7ouW.js → play-DHttF4fl.js} +1 -1
- package/payload/server/public/assets/public-DzeW3_eM.js +1 -0
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DkT63Dn4.js → quadrantDiagram-34T5L4WZ-n3bB3K91.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +1 -0
- package/payload/server/public/assets/{reduce-COyotL2V.js → reduce-DAvwat-a.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-65GGtDkc.js → requirementDiagram-MS252O5E-DiDvQK3c.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-D1vRwLWd.js → sankeyDiagram-XADWPNL6-DWDQQZmd.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-Bp47ZSN2.js → sequenceDiagram-FGHM5R23-DmAqRlBT.js} +1 -1
- package/payload/server/public/assets/square-CHcQHtK8.js +1 -0
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BZHHcP_e.js → stateDiagram-FHFEXIEX-D4R-n6bZ.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BcFRbGRu.js +1 -0
- package/payload/server/public/assets/tasks-ClfJU1CK.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-DZ1wUyj-.js → timeline-definition-GMOUNBTQ-CjiHGP4l.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-BtRr5vXp.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-D8p0sbyo.js +1 -0
- package/payload/server/public/assets/useCopyFeedback-CPEOUSGU.js +1 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-ayajZz8T.css → useSubAccountSwitcher-CdS1CorH.css} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CttBahsn.js → vennDiagram-DHZGUBPP-CBdDQ7c-.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-DgMn-9ZJ.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Y5tWieZg.js → wardleyDiagram-NUSXRM2D-BlIQPKLb.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-C78A9qbe.js → xychartDiagram-5P7HB3ND-CslKgh9B.js} +1 -1
- package/payload/server/public/browser.html +6 -6
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +13 -14
- package/payload/server/public/data.html +10 -10
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +14 -15
- package/payload/server/public/operator.html +15 -16
- package/payload/server/public/public.html +13 -14
- package/payload/server/public/tasks.html +5 -5
- package/payload/server/server.js +228 -9
- package/payload/server/public/assets/AdminLoginScreens-yAIhWcGc.js +0 -1
- package/payload/server/public/assets/AdminShell-Bk1AFQ4D.js +0 -2
- package/payload/server/public/assets/Transcript-D67OZnVM.js +0 -2
- package/payload/server/public/assets/admin-DuOhkvrZ.js +0 -1
- package/payload/server/public/assets/admin-types-ClHBm0ni.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-CgeA3HPD.js +0 -1
- package/payload/server/public/assets/calendar-CNk1iPrA.js +0 -1
- package/payload/server/public/assets/channel-B04VBWf7.js +0 -1
- package/payload/server/public/assets/chat-7qB-dwBq.js +0 -1
- package/payload/server/public/assets/chevron-left-CpcDbHIz.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-DZkHcXRA.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-D9Mwgzti.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CIo_TzfF.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-SzQYvAUZ.js +0 -1
- package/payload/server/public/assets/clone-BVjcjsBA.js +0 -1
- package/payload/server/public/assets/data-BnHcS27X.js +0 -1
- package/payload/server/public/assets/file-download-Hf_UILaA.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-DzQ18i0T.js +0 -1
- package/payload/server/public/assets/graph-klLugHEK.js +0 -51
- package/payload/server/public/assets/info-OMHHGYJF-CwsoaVzV.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-ieNsH2bV.js +0 -2
- package/payload/server/public/assets/operator-CRcySYv9.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-DxB-bO4L.js +0 -1
- package/payload/server/public/assets/page-CVo3CWIY.js +0 -1
- package/payload/server/public/assets/page-DPTbZRwl.js +0 -32
- package/payload/server/public/assets/pie-ZZUOXDRM-PSdKvB8-.js +0 -1
- package/payload/server/public/assets/public-Fi6ccYaE.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-D8FqRiWq.js +0 -1
- package/payload/server/public/assets/rotate-ccw-xHksz9mr.js +0 -1
- package/payload/server/public/assets/square-BZqaxg7D.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-qVtoGx56.js +0 -1
- package/payload/server/public/assets/tasks-COWmfts8.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-i-w4rJmQ.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-Dij6AlAj.js +0 -1
- package/payload/server/public/assets/wardley-RL74JXVD-BJhOQVqW.js +0 -1
- /package/payload/server/public/assets/{_baseFor-Bjj9It3Q.js → _baseFor-D3BqAOBr.js} +0 -0
- /package/payload/server/public/assets/{array-BrrxEo12.js → array-iYP9fzJp.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-CTWJxUxo.js → cytoscape.esm-BQSBzPsB.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-CFDbRV4k.js → defaultLocale-BrdA1gDi.js} +0 -0
- /package/payload/server/public/assets/{dist-CRpLAnCP.js → dist-Cvgxm7qv.js} +0 -0
- /package/payload/server/public/assets/{init-dXCzGgLP.js → init-Bx0S6pkp.js} +0 -0
- /package/payload/server/public/assets/{katex-CHA1JFYJ.js → katex-BsiH_a6d.js} +0 -0
- /package/payload/server/public/assets/{path-CCRpdXhK.js → path-BLSgTy3w.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-CH6UZRzu.js → preload-helper-ClBMtM1g.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-Bud4g4fh.js → rough.esm-BMOtDaaS.js} +0 -0
- /package/payload/server/public/assets/{src-xN1oULc8.js → src-DV4LKv2E.js} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DADvGnr1.js → useSubAccountSwitcher-DyjTbzQR.js} +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
// Record the size of every /api/embed POST's input array, and return one
|
|
3
|
+
// zero-vector per input so the index-aligned contract can be checked.
|
|
4
|
+
function stubFetchRecordingBatchSizes(sizes) {
|
|
5
|
+
vi.stubGlobal("fetch", vi.fn(async (_url, init) => {
|
|
6
|
+
const body = JSON.parse(init.body);
|
|
7
|
+
const inputs = Array.isArray(body.input) ? body.input : [body.input];
|
|
8
|
+
sizes.push(inputs.length);
|
|
9
|
+
return {
|
|
10
|
+
ok: true,
|
|
11
|
+
json: async () => ({ embeddings: inputs.map(() => [0]) }),
|
|
12
|
+
};
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
describe("throughput-aware embed sub-batch sizing", () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vi.restoreAllMocks();
|
|
18
|
+
vi.resetModules();
|
|
19
|
+
process.env.EMBED_REQUEST_TIMEOUT_MS = "120000";
|
|
20
|
+
process.env.EMBED_SUBBATCH_SIZE = "32";
|
|
21
|
+
process.env.EMBED_SUBBATCH_COOLDOWN_MS = "0"; // no real sleeps in test
|
|
22
|
+
});
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
delete process.env.EMBED_REQUEST_TIMEOUT_MS;
|
|
25
|
+
delete process.env.EMBED_SUBBATCH_SIZE;
|
|
26
|
+
delete process.env.EMBED_SUBBATCH_COOLDOWN_MS;
|
|
27
|
+
delete process.env.EMBED_MS_PER_INPUT;
|
|
28
|
+
});
|
|
29
|
+
it("caps each POST at min(count, duration) and keeps vectors index-aligned", async () => {
|
|
30
|
+
process.env.EMBED_MS_PER_INPUT = "6000"; // durationCap = floor(120000*0.8/6000) = 16
|
|
31
|
+
const sizes = [];
|
|
32
|
+
stubFetchRecordingBatchSizes(sizes);
|
|
33
|
+
const { embedBatch } = await import("../../lib/embeddings.js");
|
|
34
|
+
const texts = Array.from({ length: 35 }, (_, i) => `section ${i}`);
|
|
35
|
+
const out = await embedBatch(texts);
|
|
36
|
+
expect(out).toHaveLength(35);
|
|
37
|
+
expect(sizes.every((n) => n <= 16)).toBe(true); // duration cap wins over 32
|
|
38
|
+
expect(sizes.reduce((a, b) => a + b, 0)).toBe(35); // every input embedded once
|
|
39
|
+
});
|
|
40
|
+
it("lets the count cap win when per-input duration is small", async () => {
|
|
41
|
+
process.env.EMBED_MS_PER_INPUT = "1000"; // durationCap = floor(120000*0.8/1000) = 96 -> count cap 32 wins
|
|
42
|
+
const sizes = [];
|
|
43
|
+
stubFetchRecordingBatchSizes(sizes);
|
|
44
|
+
const { embedBatch } = await import("../../lib/embeddings.js");
|
|
45
|
+
await embedBatch(Array.from({ length: 40 }, (_, i) => `s${i}`));
|
|
46
|
+
expect(Math.max(...sizes)).toBe(32);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe("embed keep_alive + per-POST breadcrumb", () => {
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
vi.restoreAllMocks();
|
|
52
|
+
vi.resetModules();
|
|
53
|
+
process.env.EMBED_SUBBATCH_COOLDOWN_MS = "0";
|
|
54
|
+
});
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
delete process.env.EMBED_KEEP_ALIVE;
|
|
57
|
+
delete process.env.EMBED_SUBBATCH_COOLDOWN_MS;
|
|
58
|
+
});
|
|
59
|
+
it("sends keep_alive=-1 by default in the POST body", async () => {
|
|
60
|
+
let seenBody = {};
|
|
61
|
+
vi.stubGlobal("fetch", vi.fn(async (_u, init) => {
|
|
62
|
+
seenBody = JSON.parse(init.body);
|
|
63
|
+
return { ok: true, json: async () => ({ embeddings: [[0]] }) };
|
|
64
|
+
}));
|
|
65
|
+
const { embed } = await import("../../lib/embeddings.js");
|
|
66
|
+
await embed("hello");
|
|
67
|
+
expect(seenBody.keep_alive).toBe(-1);
|
|
68
|
+
});
|
|
69
|
+
it("treats an empty-string EMBED_KEEP_ALIVE env as unset (defaults to -1)", async () => {
|
|
70
|
+
process.env.EMBED_KEEP_ALIVE = "";
|
|
71
|
+
let seenBody = {};
|
|
72
|
+
vi.stubGlobal("fetch", vi.fn(async (_u, init) => {
|
|
73
|
+
seenBody = JSON.parse(init.body);
|
|
74
|
+
return { ok: true, json: async () => ({ embeddings: [[0]] }) };
|
|
75
|
+
}));
|
|
76
|
+
const { embed } = await import("../../lib/embeddings.js");
|
|
77
|
+
await embed("hello");
|
|
78
|
+
expect(seenBody.keep_alive).toBe(-1);
|
|
79
|
+
});
|
|
80
|
+
it("writes a per-POST breadcrumb on success", async () => {
|
|
81
|
+
vi.stubGlobal("fetch", vi.fn(async () => ({ ok: true, json: async () => ({ embeddings: [[0]] }) })));
|
|
82
|
+
const writes = [];
|
|
83
|
+
vi.spyOn(process.stderr, "write").mockImplementation((s) => {
|
|
84
|
+
writes.push(String(s));
|
|
85
|
+
return true;
|
|
86
|
+
});
|
|
87
|
+
const { embed } = await import("../../lib/embeddings.js");
|
|
88
|
+
await embed("hello");
|
|
89
|
+
expect(writes.some((w) => /\[embed\] op=post inputs=1 /.test(w))).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=embed-throughput.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-throughput.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/embed-throughput.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-timeout.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/embed-timeout.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
describe("embed request timeout + enriched errors", () => {
|
|
3
|
+
beforeEach(() => {
|
|
4
|
+
vi.restoreAllMocks();
|
|
5
|
+
process.env.EMBED_REQUEST_TIMEOUT_MS = "50";
|
|
6
|
+
// These tests assert enriched errors for a whole POST (inputs=2), not
|
|
7
|
+
// sub-batch sizing. Throughput-aware sizing (Task 1533) derives the POST
|
|
8
|
+
// size from the timeout, and a 50 ms timeout would otherwise floor the
|
|
9
|
+
// batch to one input per POST. Pin a 1 ms per-input estimate so the
|
|
10
|
+
// 2-input batch stays a single POST and the error still names inputs=2.
|
|
11
|
+
process.env.EMBED_MS_PER_INPUT = "1";
|
|
12
|
+
vi.resetModules();
|
|
13
|
+
});
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
delete process.env.EMBED_REQUEST_TIMEOUT_MS;
|
|
16
|
+
delete process.env.EMBED_MS_PER_INPUT;
|
|
17
|
+
});
|
|
18
|
+
it("rejects promptly with an enriched timeout error, not a bare fetch failed", async () => {
|
|
19
|
+
// Honour the abort signal: never resolve, reject when the timeout fires.
|
|
20
|
+
vi.stubGlobal("fetch", vi.fn((_u, init) => new Promise((_res, rej) => {
|
|
21
|
+
init.signal.addEventListener("abort", () => rej(init.signal.reason ?? new Error("aborted")));
|
|
22
|
+
})));
|
|
23
|
+
const { embed } = await import("../../lib/embeddings.js");
|
|
24
|
+
const start = Date.now();
|
|
25
|
+
await expect(embed("hello")).rejects.toThrow(/timed out/i);
|
|
26
|
+
// Nowhere near undici's 300000ms default.
|
|
27
|
+
expect(Date.now() - start).toBeLessThan(5000);
|
|
28
|
+
});
|
|
29
|
+
it("names input count and largest input size in the timeout error", async () => {
|
|
30
|
+
vi.stubGlobal("fetch", vi.fn((_u, init) => new Promise((_res, rej) => {
|
|
31
|
+
init.signal.addEventListener("abort", () => rej(init.signal.reason ?? new Error("aborted")));
|
|
32
|
+
})));
|
|
33
|
+
const { embedBatch } = await import("../../lib/embeddings.js");
|
|
34
|
+
await expect(embedBatch(["a", "bbbb"])).rejects.toThrow(/timed out.*inputs=2.*largestInputChars=4/s);
|
|
35
|
+
});
|
|
36
|
+
it("names the underlying cause on a connection failure, not a bare fetch failed", async () => {
|
|
37
|
+
// Mirrors undici on a refused connection: TypeError("fetch failed", { cause }).
|
|
38
|
+
vi.stubGlobal("fetch", vi.fn(async () => {
|
|
39
|
+
throw new TypeError("fetch failed", {
|
|
40
|
+
cause: new Error("connect ECONNREFUSED 127.0.0.1:11434"),
|
|
41
|
+
});
|
|
42
|
+
}));
|
|
43
|
+
const { embed } = await import("../../lib/embeddings.js");
|
|
44
|
+
await expect(embed("hello")).rejects.toThrow(/failed.*inputs=1.*largestInputChars=5.*ECONNREFUSED/s);
|
|
45
|
+
});
|
|
46
|
+
it("enriches an HTTP error with status, input count and largest input size", async () => {
|
|
47
|
+
vi.stubGlobal("fetch", vi.fn(async () => ({
|
|
48
|
+
ok: false,
|
|
49
|
+
status: 400,
|
|
50
|
+
text: async () => '{"error":"the input length exceeds the context length"}',
|
|
51
|
+
})));
|
|
52
|
+
const { embedBatch } = await import("../../lib/embeddings.js");
|
|
53
|
+
await expect(embedBatch(["a", "bbbb"])).rejects.toThrow(/400.*inputs=2.*largestInputChars=4/s);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=embed-timeout.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-timeout.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/embed-timeout.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,4 +31,60 @@ describe("embed input capping", () => {
|
|
|
31
31
|
expect(sent[1].length).toBe(EMBED_INPUT_MAX_CHARS);
|
|
32
32
|
});
|
|
33
33
|
});
|
|
34
|
+
describe("token-safe cap default", () => {
|
|
35
|
+
beforeEach(() => vi.restoreAllMocks());
|
|
36
|
+
it("defaults to 6000 chars, provably under a 2048-token context at 3 chars/token", async () => {
|
|
37
|
+
const { EMBED_INPUT_MAX_CHARS } = await import("../../lib/embeddings.js");
|
|
38
|
+
expect(EMBED_INPUT_MAX_CHARS).toBe(6000);
|
|
39
|
+
// 6000 chars / 3 chars-per-token = 2000 tokens <= 2048 context
|
|
40
|
+
expect(EMBED_INPUT_MAX_CHARS / 3).toBeLessThanOrEqual(2048);
|
|
41
|
+
});
|
|
42
|
+
it("caps a dense 24k-char emoji/markup body to <= 6000 chars before POST", async () => {
|
|
43
|
+
const dense = "🟢🟡🔴 ## Observatory\n".repeat(1400); // ~24k chars
|
|
44
|
+
let sent = "";
|
|
45
|
+
vi.stubGlobal("fetch", vi.fn(async (_u, init) => {
|
|
46
|
+
sent = JSON.parse(init.body).input;
|
|
47
|
+
return {
|
|
48
|
+
ok: true,
|
|
49
|
+
json: async () => ({ embeddings: [[0.1]] }),
|
|
50
|
+
};
|
|
51
|
+
}));
|
|
52
|
+
const { embed, EMBED_INPUT_MAX_CHARS } = await import("../../lib/embeddings.js");
|
|
53
|
+
await embed(dense);
|
|
54
|
+
expect(sent.length).toBeLessThanOrEqual(6000);
|
|
55
|
+
expect(sent.length).toBe(EMBED_INPUT_MAX_CHARS);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe("multi-section document batch (exitchatcontrol regression)", () => {
|
|
59
|
+
beforeEach(() => vi.restoreAllMocks());
|
|
60
|
+
it("embeds a mix of short and dense oversized sections with no 400 and no timeout", async () => {
|
|
61
|
+
// Resembles ingesting a document: a summary plus several sections, one of
|
|
62
|
+
// them the dense emoji/markup 'observatory' chapter that used to 400.
|
|
63
|
+
const sections = [
|
|
64
|
+
"Exit Chat Control summary.",
|
|
65
|
+
"🟢🟡🔴 ## Observatory\n".repeat(1400), // ~30k dense chars
|
|
66
|
+
"A normal-length prose section about the campaign.",
|
|
67
|
+
"🔴🔴🔴 status matrix ".repeat(600),
|
|
68
|
+
"Closing section.",
|
|
69
|
+
];
|
|
70
|
+
const sentInputs = [];
|
|
71
|
+
vi.stubGlobal("fetch", vi.fn(async (_u, init) => {
|
|
72
|
+
const inp = JSON.parse(init.body).input;
|
|
73
|
+
sentInputs.push(inp);
|
|
74
|
+
return {
|
|
75
|
+
ok: true,
|
|
76
|
+
json: async () => ({ embeddings: inp.map(() => [0.1]) }),
|
|
77
|
+
};
|
|
78
|
+
}));
|
|
79
|
+
const { embedBatch } = await import("../../lib/embeddings.js");
|
|
80
|
+
const vectors = await embedBatch(sections);
|
|
81
|
+
// One vector per section, index-aligned.
|
|
82
|
+
expect(vectors).toHaveLength(sections.length);
|
|
83
|
+
// Every input actually POSTed was within the token-safe cap.
|
|
84
|
+
for (const batch of sentInputs) {
|
|
85
|
+
for (const s of batch)
|
|
86
|
+
expect(s.length).toBeLessThanOrEqual(6000);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
34
90
|
//# sourceMappingURL=embeddings-cap.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings-cap.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/embeddings-cap.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE9D,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;IAEvC,EAAE,CAAC,mFAAmF,EAAE,KAAK,IAAI,EAAE;QACjG,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,SAAkB,CAAC;QACvB,EAAE,CAAC,UAAU,CACX,OAAO,EACP,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,IAAsB,EAAE,EAAE;YACnD,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;YACxC,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;aAC1B,CAAC;QAC3B,CAAC,CAAC,CACH,CAAC;QACF,MAAM,EAAE,KAAK,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QACjF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAChC,MAAM,CAAE,SAAoB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,IAAI,IAAI,GAAa,EAAE,CAAC;QACxB,EAAE,CAAC,UAAU,CACX,OAAO,EACP,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,IAAsB,EAAE,EAAE;YACjD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;YACnC,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;aACnC,CAAC;QAC3B,CAAC,CAAC,CACH,CAAC;QACF,MAAM,EAAE,UAAU,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QACtF,MAAM,UAAU,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"embeddings-cap.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/embeddings-cap.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Non-fatal embedding: returns empty array if
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Non-fatal embedding: returns an empty array if the shared embed client fails
|
|
3
|
+
* (Ollama unavailable, slow or wedged past the request timeout, or a dense body
|
|
4
|
+
* that still errors after the token-safe cap). Task operations succeed without
|
|
5
|
+
* an embedding — memory-search just will not find the node by similarity until
|
|
6
|
+
* the next update re-embeds. Delegates the POST to platform/lib/embed-client so
|
|
7
|
+
* the token-safe cap, the explicit request timeout, and the cause-naming error
|
|
8
|
+
* are inherited (Task 1530). The failure the shared client would throw is caught
|
|
9
|
+
* here and downgraded to `[]`, but first written as a greppable breadcrumb so a
|
|
10
|
+
* swallowed embed is diagnosable rather than silent.
|
|
5
11
|
*/
|
|
6
12
|
export declare function computeEmbedding(text: string): Promise<number[]>;
|
|
7
13
|
//# sourceMappingURL=embeddings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAetE"}
|
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
const EMBED_MODEL = process.env.EMBED_MODEL ?? "nomic-embed-text";
|
|
1
|
+
import { embed } from "../../../../../lib/embed-client/dist/index.js";
|
|
3
2
|
/**
|
|
4
|
-
* Non-fatal embedding: returns empty array if
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* Non-fatal embedding: returns an empty array if the shared embed client fails
|
|
4
|
+
* (Ollama unavailable, slow or wedged past the request timeout, or a dense body
|
|
5
|
+
* that still errors after the token-safe cap). Task operations succeed without
|
|
6
|
+
* an embedding — memory-search just will not find the node by similarity until
|
|
7
|
+
* the next update re-embeds. Delegates the POST to platform/lib/embed-client so
|
|
8
|
+
* the token-safe cap, the explicit request timeout, and the cause-naming error
|
|
9
|
+
* are inherited (Task 1530). The failure the shared client would throw is caught
|
|
10
|
+
* here and downgraded to `[]`, but first written as a greppable breadcrumb so a
|
|
11
|
+
* swallowed embed is diagnosable rather than silent.
|
|
7
12
|
*/
|
|
8
13
|
export async function computeEmbedding(text) {
|
|
9
14
|
try {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return [];
|
|
17
|
-
const data = (await res.json());
|
|
18
|
-
return data.embeddings[0] ?? [];
|
|
15
|
+
// Coerce to [] so the returns-[] contract holds even on the shared client's
|
|
16
|
+
// one non-throwing empty-result path: an empty input string makes ollama
|
|
17
|
+
// answer HTTP 200 with `embeddings: []`, so embed() resolves undefined
|
|
18
|
+
// rather than rejecting. The old local client guarded this with the same
|
|
19
|
+
// `?? []`; keep it so a caller never reads `.length` on undefined.
|
|
20
|
+
return (await embed(text)) ?? [];
|
|
19
21
|
}
|
|
20
|
-
catch {
|
|
22
|
+
catch (err) {
|
|
23
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
24
|
+
process.stderr.write(`[work-embed] op=failed inputChars=${text.length} reason=${reason}\n`);
|
|
21
25
|
return [];
|
|
22
26
|
}
|
|
23
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,+CAA+C,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,IAAI,CAAC;QACH,4EAA4E;QAC5E,yEAAyE;QACzE,uEAAuE;QACvE,yEAAyE;QACzE,mEAAmE;QACnE,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qCAAqC,IAAI,CAAC,MAAM,WAAW,MAAM,IAAI,CACtE,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { embed } from "../../../../../lib/embed-client/dist/index.js";
|
|
2
2
|
//# sourceMappingURL=embeddings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,+CAA+C,CAAC"}
|
|
@@ -1,19 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
});
|
|
9
|
-
if (!res.ok) {
|
|
10
|
-
const body = await res.text();
|
|
11
|
-
throw new Error(`Ollama embedding failed (${res.status}): ${body}`);
|
|
12
|
-
}
|
|
13
|
-
const data = (await res.json());
|
|
14
|
-
if (!Array.isArray(data.embeddings) || data.embeddings.length === 0) {
|
|
15
|
-
throw new Error("Ollama returned invalid embedding response — expected non-empty embeddings array");
|
|
16
|
-
}
|
|
17
|
-
return data.embeddings[0];
|
|
18
|
-
}
|
|
1
|
+
// The Ollama embed client lives in platform/lib/embed-client so every writer
|
|
2
|
+
// shares one capped, timeout-guarded, cause-naming implementation (Task 636,
|
|
3
|
+
// 1529). This module re-exports it to preserve the `../lib/embeddings.js`
|
|
4
|
+
// import site in the workflows plugin (Task 1530). Migrating drops the old
|
|
5
|
+
// non-empty-array guard: the shared client omits it, and it fired only on an
|
|
6
|
+
// impossible HTTP-200-with-empty-embeddings response.
|
|
7
|
+
export { embed } from "../../../../../lib/embed-client/dist/index.js";
|
|
19
8
|
//# sourceMappingURL=embeddings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6EAA6E;AAC7E,0EAA0E;AAC1E,2EAA2E;AAC3E,6EAA6E;AAC7E,sDAAsD;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,+CAA+C,CAAC"}
|
|
@@ -4333,22 +4333,77 @@ process.on("SIGINT", async () => {
|
|
|
4333
4333
|
});
|
|
4334
4334
|
var OLLAMA_URL = process.env.OLLAMA_URL ?? "http://localhost:11434";
|
|
4335
4335
|
var EMBED_MODEL = process.env.EMBED_MODEL ?? "nomic-embed-text";
|
|
4336
|
-
|
|
4337
|
-
|
|
4336
|
+
function envInt(name, def) {
|
|
4337
|
+
const raw2 = process.env[name];
|
|
4338
|
+
if (raw2 === void 0 || raw2 === "") return def;
|
|
4339
|
+
const n = Number(raw2);
|
|
4340
|
+
return Number.isFinite(n) ? n : def;
|
|
4341
|
+
}
|
|
4342
|
+
var EMBED_MODEL_CONTEXT_TOKENS = Math.max(1, Math.floor(envInt("EMBED_MODEL_CONTEXT_TOKENS", 2048)));
|
|
4343
|
+
var EMBED_CONTEXT_MARGIN_TOKENS = 48;
|
|
4344
|
+
var EMBED_WORST_CASE_CHARS_PER_TOKEN = 3;
|
|
4345
|
+
var EMBED_INPUT_MAX_CHARS = Math.max(
|
|
4346
|
+
1,
|
|
4347
|
+
Math.floor(
|
|
4348
|
+
envInt(
|
|
4349
|
+
"EMBED_INPUT_MAX_CHARS",
|
|
4350
|
+
(EMBED_MODEL_CONTEXT_TOKENS - EMBED_CONTEXT_MARGIN_TOKENS) * EMBED_WORST_CASE_CHARS_PER_TOKEN
|
|
4351
|
+
)
|
|
4352
|
+
)
|
|
4353
|
+
);
|
|
4354
|
+
var EMBED_KEEP_ALIVE_RAW = process.env.EMBED_KEEP_ALIVE === void 0 || process.env.EMBED_KEEP_ALIVE === "" ? "-1" : process.env.EMBED_KEEP_ALIVE;
|
|
4355
|
+
var EMBED_KEEP_ALIVE = /^-?\d+$/.test(EMBED_KEEP_ALIVE_RAW) ? Number(EMBED_KEEP_ALIVE_RAW) : EMBED_KEEP_ALIVE_RAW;
|
|
4356
|
+
var EMBED_INTERACTIVE_TIMEOUT_MS = 5e3;
|
|
4357
|
+
var EMBED_PRELOAD_TIMEOUT_MS = 6e4;
|
|
4358
|
+
async function embed(text, timeoutMs = EMBED_INTERACTIVE_TIMEOUT_MS) {
|
|
4338
4359
|
const input = text.length > EMBED_INPUT_MAX_CHARS ? text.slice(0, EMBED_INPUT_MAX_CHARS) : text;
|
|
4339
|
-
const
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4360
|
+
const startedAt = Date.now();
|
|
4361
|
+
const target = `${OLLAMA_URL}/api/embed`;
|
|
4362
|
+
let res;
|
|
4363
|
+
try {
|
|
4364
|
+
res = await fetch(target, {
|
|
4365
|
+
method: "POST",
|
|
4366
|
+
headers: { "Content-Type": "application/json" },
|
|
4367
|
+
body: JSON.stringify({ model: EMBED_MODEL, input, keep_alive: EMBED_KEEP_ALIVE }),
|
|
4368
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
4369
|
+
});
|
|
4370
|
+
} catch (err) {
|
|
4371
|
+
const name = err instanceof Error ? err.name : "";
|
|
4372
|
+
if (name === "TimeoutError" || name === "AbortError") {
|
|
4373
|
+
throw new Error(
|
|
4374
|
+
`Ollama embed request timed out after ${timeoutMs}ms (inputChars=${input.length}) at ${target}; ollama did not respond in time (slow, cold-loading, or CPU-saturated).`
|
|
4375
|
+
);
|
|
4376
|
+
}
|
|
4377
|
+
let detail = err instanceof Error ? err.message : String(err);
|
|
4378
|
+
const cause = err instanceof Error ? err.cause : void 0;
|
|
4379
|
+
if (cause !== void 0) {
|
|
4380
|
+
detail += `: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
4381
|
+
}
|
|
4382
|
+
throw new Error(
|
|
4383
|
+
`Ollama embed request failed (inputChars=${input.length}) at ${target}: ${detail}`
|
|
4384
|
+
);
|
|
4385
|
+
}
|
|
4345
4386
|
if (!res.ok) {
|
|
4346
4387
|
const body = await res.text();
|
|
4347
|
-
throw new Error(
|
|
4388
|
+
throw new Error(
|
|
4389
|
+
`Ollama embedding failed (HTTP ${res.status}, inputChars=${input.length}): ${body}`
|
|
4390
|
+
);
|
|
4348
4391
|
}
|
|
4349
4392
|
const data = await res.json();
|
|
4393
|
+
const ms = Date.now() - startedAt;
|
|
4394
|
+
console.error(`[embed-query] warmth=${ms > 1e3 ? "cold" : "warm"} ms=${ms}`);
|
|
4350
4395
|
return data.embeddings[0];
|
|
4351
4396
|
}
|
|
4397
|
+
async function preloadEmbedModel() {
|
|
4398
|
+
try {
|
|
4399
|
+
await embed("warm", EMBED_PRELOAD_TIMEOUT_MS);
|
|
4400
|
+
console.error("[embed-query] op=preload result=ok");
|
|
4401
|
+
} catch (err) {
|
|
4402
|
+
console.error(
|
|
4403
|
+
`[embed-query] op=preload result=skip err="${err instanceof Error ? err.message : String(err)}"`
|
|
4404
|
+
);
|
|
4405
|
+
}
|
|
4406
|
+
}
|
|
4352
4407
|
var sessionStoreRef = null;
|
|
4353
4408
|
function getCachedSessionId(cacheKey2) {
|
|
4354
4409
|
return sessionStoreRef?.get(cacheKey2)?.sessionId;
|
|
@@ -5914,6 +5969,7 @@ export {
|
|
|
5914
5969
|
runAdminUserSelfHeal,
|
|
5915
5970
|
runUserProfileReconcile,
|
|
5916
5971
|
embed,
|
|
5972
|
+
preloadEmbedModel,
|
|
5917
5973
|
GREETING_DIRECTIVE,
|
|
5918
5974
|
ensureConversation,
|
|
5919
5975
|
findRecentConversation,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e}from"./chunk-Ck5AOu5v.js";import{_ as t,b as n,h as r,w as i,y as a}from"./useSubAccountSwitcher-DyjTbzQR.js";import{C as o}from"./audio-attachment-mime-BBW07eyG.js";import{b as s,y as c}from"./AdminShell-BfLQQ27Z.js";import{t as l}from"./Checkbox-BC0c_gbn.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(i(),1);function m(e=`admin`){let[t,r]=(0,p.useState)(`loading`),[i,a]=(0,p.useState)(``),[c,l]=(0,p.useState)(``),[m,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(!1),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(null),[A,j]=(0,p.useState)(void 0),[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(void 0),[I,L]=(0,p.useState)(null),[R,z]=(0,p.useState)(null),[B,V]=(0,p.useState)(void 0),H=(0,p.useRef)(void 0),[U,W]=(0,p.useState)(!1),[G,K]=(0,p.useState)(!0);(0,p.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&W(!0)}).catch(()=>{})},[]);let q=(0,p.useRef)(null),J=(0,p.useRef)(null);(0,p.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let n=await t.json();D(n.session_key),z(n.sessionId??null),j(n.businessName),N(n.role??null),F(n.userName===void 0?null:n.userName),L(n.avatar??null);let i=o(n.thinkingView);return H.current=i,V(i),r(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(n=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check returned ${i.status} after retries`),r(`set-pin`);return}let a=await i.json();if(!a.pin_configured){r(`set-pin`);return}K(!!a.claude_authenticated);let o=!1;try{o=new URLSearchParams(window.location.search).get(`connect`)===`claude`}catch{}if(o){try{let e=new URL(window.location.href);e.searchParams.delete(`connect`),window.history.replaceState(null,``,e.pathname+e.search+e.hash)}catch{}if(!a.claude_authenticated){r(`connect-claude`);return}}if(await e())return;r(`enter-pin`)}catch(e){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check failed:`,e),r(`set-pin`)}}t()},[]),(0,p.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,p.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(u)===`1`}catch{}if(f({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(u,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${d}`),window.location.replace(d)}},[t,e]);let Y=(0,p.useRef)(null);(0,p.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();K(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){n(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),Y.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,p.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&(K(!0),r(`enter-pin`))}).catch(()=>{})},[t]);async function X(e,t){y(!0);try{let i=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!i.ok){let e=await i.json().catch(()=>({}));if(i.status===401&&e?.code===`remote-auth-required`){n(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await i.json();D(s.session_key),z(s.sessionId??null),j(s.businessName),N(s.role??null),F(s.userName===void 0?null:s.userName),L(s.avatar??null);let c=o(s.thinkingView);H.current=c,V(c);try{sessionStorage.setItem(`maxy-admin-session-key`,s.session_key)}catch{}a(``),r(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Z=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=c.trim();if(!t){h(`Please enter your name.`);return}if(i.length<4){h(`PIN must be at least 4 characters.`);return}let o=i;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===401&&t?.code===`remote-auth-required`){n(`set-pin`,`/api/onboarding/set-pin`);return}if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let n=await e.json();n.pin_configured&&n.claude_authenticated?r(`enter-pin`):n.pin_configured?r(`connect-claude`):h(t.error||`Failed to set PIN.`)}else r(`enter-pin`)}catch{r(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let i=await fetch(`/api/health`);if((i.ok?await i.json():null)?.claude_authenticated){await X(o);return}a(``),r(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[i,v,c]),Q=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await X(i)},[i]),ee=(0,p.useCallback)(async()=>{T(!0);try{if(!await s())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;K(!1),D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return r(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,p.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}a(``),h(``),r(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:r,pin:i,setPin:a,operatorName:c,setOperatorName:l,pinError:m,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:R,setSessionId:z,expandAll:B,setExpandAll:V,expandAllDefaultRef:H,remoteAuthEnabled:U,claudeConnected:G,pinInputRef:q,setPinFormRef:J,handleSetPin:Z,handleLogin:Q,handleDisconnect:ee,handleLogout:$}}var h=a();function g({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,p.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,h.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,h.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function _(e){let{pin:n,setPin:i,showPin:a,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:_}=e;return(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,r.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,r.productName,` who you are, then choose a PIN.`]}),(0,h.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,h.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:i,onComplete:()=>{},showPin:a}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!n||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(l,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:n,setPin:i,showPin:a,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:m}=e;return(0,h.jsxs)(`div`,{className:`connect-page`,children:[p&&m&&(0,h.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:m,children:`Sign out`}),(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:r.productName}),(0,h.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:i,onComplete:()=>{},showPin:a,autoFocus:!0}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!n,loading:s,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(`div`,{className:`pin-options`,children:(0,h.jsx)(l,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:n,setAuthPolling:i,authLoading:a,setAuthLoading:o,pinError:s,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1),[_,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(``);async function C(){S(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:y})})).json();e.accepted?(S(`Code submitted. Finishing sign-in…`),b(``)):S(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),S(`Could not submit code.`)}}async function w(){g(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}g(!1)}async function T(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){i(!0),f(!0),o(!1),v(e.transport||``);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),i(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function E(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),i(!1),l(``)}return n||d?(0,h.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,h.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[n?(0,h.jsx)(`button`,{onClick:E,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,h.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,h.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,h.jsx)(`p`,{className:`chat-intro`,children:n?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!n&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(c,{variant:`primary`,onClick:T,disabled:a,children:a?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),n&&_===`native`&&(0,h.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,h.jsx)(`label`,{style:{fontSize:`12px`,color:`#999`,lineHeight:1.4},children:`If the browser didn't finish sign-in, paste the code or full redirect URL from Claude's page:`}),(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,h.jsx)(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,h.jsx)(c,{variant:`primary`,onClick:C,disabled:!y.trim(),children:`Submit`})]}),x&&(0,h.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:x})]})]}),(0,h.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,h.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsxs)(`div`,{className:`connect-logos`,children:[(0,h.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,h.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,h.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,h.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,h.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:r.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,r.productName]}),(0,h.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,h.jsx)(c,{variant:`primary`,onClick:T,disabled:a,children:a?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,h.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,h.jsx)(`button`,{onClick:w,disabled:m,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:m?`Launching…`:`Open browser first`}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function b({auth:e}){return e.appState===`loading`?(0,h.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,h.jsx)(_,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,h.jsx)(y,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,h.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):null}export{m as n,b as t};
|