@rubytech/create-maxy-code 0.1.435 → 0.1.437
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/docs/superpowers/plans/2026-07-11-task-1557-operator-on-behalf-preference-attribution.md +542 -0
- package/payload/platform/docs/superpowers/specs/2026-07-11-task-1557-operator-on-behalf-preference-attribution-design.md +90 -0
- package/payload/platform/lib/active-rules/dist/index.d.ts +14 -0
- package/payload/platform/lib/active-rules/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/active-rules/dist/index.js +56 -9
- package/payload/platform/lib/active-rules/dist/index.js.map +1 -1
- package/payload/platform/lib/active-rules/src/index.test.ts +106 -0
- package/payload/platform/lib/active-rules/src/index.ts +98 -9
- package/payload/platform/lib/embed-client/dist/index.d.ts +1 -1
- package/payload/platform/lib/embed-client/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/embed-client/dist/index.js +42 -13
- package/payload/platform/lib/embed-client/dist/index.js.map +1 -1
- package/payload/platform/lib/embed-client/src/index.ts +44 -13
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +7 -7
- package/payload/platform/plugins/docs/references/admin-session.md +2 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/plugins/docs/references/internals.md +4 -4
- package/payload/platform/plugins/memory/PLUGIN.md +2 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +54 -25
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/embed-progress-reporter.d.ts +22 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/embed-progress-reporter.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/embed-progress-reporter.js +43 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/embed-progress-reporter.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/profile-identity.d.ts +34 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/profile-identity.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/profile-identity.js +22 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/profile-identity.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/resolve-admin-home-account.d.ts +13 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/resolve-admin-home-account.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/resolve-admin-home-account.js +26 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/resolve-admin-home-account.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-progress-reporter.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-progress-reporter.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-progress-reporter.test.js +52 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-progress-reporter.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-progress.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-progress.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-progress.test.js +56 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-progress.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-throughput.test.js +30 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embed-throughput.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js +9 -7
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.js +79 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.js +50 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.js +114 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-identity.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-identity.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-identity.test.js +72 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-identity.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-read-active-rules.test.js +5 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-read-active-rules.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-bootstrap.test.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-bootstrap.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-admin-home-account.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-admin-home-account.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-admin-home-account.test.js +38 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-admin-home-account.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +15 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +17 -17
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +9 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +22 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +19 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +4 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +5 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +8 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +16 -6
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts +7 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js +9 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.d.ts +4 -1
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.js.map +1 -1
- package/payload/server/{chunk-DAYMXQG2.js → chunk-LMLVOZ6G.js} +7 -2
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-CMh1pdOp.js → AdminLoginScreens-DeR71H29.js} +1 -1
- package/payload/server/public/assets/AdminShell-DlAVQUda.js +2 -0
- package/payload/server/public/assets/{Checkbox-OCfZCTCO.js → Checkbox-B629mOPp.js} +1 -1
- package/payload/server/public/assets/{admin-Bi2uYnAg.js → admin-C15h-NL0.js} +1 -1
- package/payload/server/public/assets/{arc-Bm9oSOth.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-C2dK88g3.js → architectureDiagram-Q4EWVU46-DkVrGn7G.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DfLSsjCJ.js → blockDiagram-DXYQGD6D-DqavswGH.js} +1 -1
- package/payload/server/public/assets/browser-B7xQLIRK.js +1 -0
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-Bxkmp6OL.js → c4Diagram-AHTNJAMY-B7fyKiXe.js} +1 -1
- package/payload/server/public/assets/calendar-A-vGm6pL.js +1 -0
- package/payload/server/public/assets/channel-j70eMvcL.js +1 -0
- package/payload/server/public/assets/chat-DAae6Z51.js +1 -0
- package/payload/server/public/assets/chevron-left-u4tjq7fI.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-BVNDFwNH.js → chunk-2KRD3SAO-DsgMtGkv.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-Daz6nMta.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-DTldfvwP.js → chunk-4BX2VUAB-CYpiF2bl.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-DhM8pwRG.js → chunk-4TB4RGXK-CWyc_F7v.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-CzTsbIHo.js → chunk-55IACEB6-BbzKMw2Z.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-BrcObZhe.js → chunk-5FUZZQ4R-u19Nai9e.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-SFqTuS11.js → chunk-5PVQY5BW-Ba8by6Uy.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-EIbrSGOo.js → chunk-67CJDMHE-BwUuxtyb.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-B1D4Jorr.js → chunk-7N4EOEYR-BRH9iM9L.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-BKHiX4cC.js → chunk-AA7GKIK3-BGoztgLL.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-xBzu29m7.js → chunk-BSJP7CBP-C5GDAZTl.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-x2x0gMpL.js → chunk-CIAEETIT-ChY32VPS.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-D5UkD28M.js → chunk-EDXVE4YY-CPSD3p6p.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-Dbz67a7E.js → chunk-ENJZ2VHE-D1oL-iUr.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-XfWvuu2F.js → chunk-FMBD7UC4-CPvYEr54.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-DfOEDS4q.js → chunk-FOC6F5B3-9Yyj7Vbz.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-D_WEZZvg.js → chunk-ICPOFSXX-BaYgh8FR.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-7O627Xi1.js → chunk-K5T4RW27-5ucpeRvm.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-BXI3XDP9.js → chunk-KGLVRYIC-DW-FHk7T.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-B9cFNN0l.js → chunk-LIHQZDEY-CGGVfAyG.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-BR3UNDTn.js → chunk-ORNJ4GCN-Bv8EUa5d.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-2wKIEtFZ.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-augM3AXB.js → chunk-U2HBQHQK-PwSQz6EP.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-BAM9q9ZQ.js → chunk-X2U36JSP--NPHTBlU.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-DxPpji5P.js → chunk-XPW4576I-Bbc7Da32.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-BD3ClFXP.js → chunk-YZCP3GAM-D-9v8e--.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-CqxhLPep.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-xywWX-9i.js → cose-bilkent-S5V4N54A-NVSb1Bhy.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-ChRpqqiH.js → dagre-KV5264BT-V2Ai1DFl.js} +1 -1
- package/payload/server/public/assets/{dagre-BaHjDQ-8.js → dagre-QfLcO-1j.js} +1 -1
- package/payload/server/public/assets/data-BNWpKx1d.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-KjwTpyBi.js → diagram-5BDNPKRD-Caw21693.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-DZO9njAF.js → diagram-G4DWMVQ6-CgwVkT2q.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-Bus-U-TI.js → diagram-MMDJMWI5-DFUrLZhs.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CfJodFgq.js → diagram-TYMM5635-CEEiEuZJ.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-Bt5zqWiW.js → erDiagram-SMLLAGMA-CG10NrT3.js} +1 -1
- package/payload/server/public/assets/file-download-4mKJxUi-.js +1 -0
- package/payload/server/public/assets/{flatten-Bpu1L63d.js → flatten-DAO0sfCM.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B64Q590S.js → flowDiagram-DWJPFMVM-BqkV9Okv.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BWdgCEpH.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-Djq2B0WT.js → gitGraphDiagram-UUTBAWPF-BZV2voyy.js} +1 -1
- package/payload/server/public/assets/{graph-CrJ-itbq.js → graph-D0orIRAh.js} +3 -3
- package/payload/server/public/assets/{graph-labels-CmCWaKJT.js → graph-labels-B8YAdo3Z.js} +1 -1
- package/payload/server/public/assets/{graphlib-CNJh9_lx.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-DkDEVnMZ.js → isEmpty-Cb_U81C6.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-V3ACkWCW.js → ishikawaDiagram-UXIWVN3A-BKsAxSvp.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-9T0qZeH3.js → journeyDiagram-VCZTEJTY-CmliuOd-.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CxZ0ukx3.js → kanban-definition-6JOO6SKY-DAlElMb-.js} +1 -1
- package/payload/server/public/assets/{line-DUHKCQZT.js → line-DKZqLKAC.js} +1 -1
- package/payload/server/public/assets/{linear-BgIBblun.js → linear-CbSGdh1x.js} +1 -1
- package/payload/server/public/assets/{maximize-2-_cJWIgx2.js → maximize-2-CxstTgoK.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-CyHygs0-.js → mermaid-parser.core-DFvbao9C.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-L55fJBSx.js → mermaid.core-C0vEBxDm.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DczaUX_E.js → mindmap-definition-QFDTVHPH-CShASUKd.js} +1 -1
- package/payload/server/public/assets/operator-DZzuotDB.js +1 -0
- package/payload/server/public/assets/{ordinal-DK3QISRR.js → ordinal-H0tVmBDP.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +1 -0
- package/payload/server/public/assets/page-3g0A19Rv.js +32 -0
- package/payload/server/public/assets/page-Ck_pLhAk.js +1 -0
- package/payload/server/public/assets/{pdf-render-COLA4aPx.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-Da5TdnNt.js → pieDiagram-DEJITSTG-CBZHpDAJ.js} +1 -1
- package/payload/server/public/assets/{public-DmBKnBkr.js → public-WFUQw9AD.js} +1 -1
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DX7J81uh.js → quadrantDiagram-34T5L4WZ-n3bB3K91.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +1 -0
- package/payload/server/public/assets/{reduce-uzWdoyL7.js → reduce-DAvwat-a.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DJQGrZPG.js → requirementDiagram-MS252O5E-DiDvQK3c.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-COGQTi7n.js +1 -0
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Ba8fGz96.js → sankeyDiagram-XADWPNL6-DWDQQZmd.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BmDPC7qx.js → sequenceDiagram-FGHM5R23-DmAqRlBT.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-1VkptYFz.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-B97VpwEJ.js +1 -0
- package/payload/server/public/assets/{time-entry-format-D477WAes.js → time-entry-format-C09rDHo9.js} +1 -1
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-B92U3T_f.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-CSk9KjhY.js +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DLJFISqf.js +9 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-BKCWKo97.css → useSubAccountSwitcher-Dzmd7Aip.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-CZPtVpM-.js → useVoiceRecorder-DCyJQkFK.js} +2 -2
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-Y6Wkihrs.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-iJpfal2z.js → wardleyDiagram-NUSXRM2D-BlIQPKLb.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-S0bv7oH0.js → xychartDiagram-5P7HB3ND-CslKgh9B.js} +1 -1
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +13 -12
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +11 -10
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +15 -14
- package/payload/server/public/public.html +13 -12
- package/payload/server/public/tasks.html +5 -4
- package/payload/server/server.js +691 -542
- package/payload/server/public/assets/AdminShell-X9Bg3AKc.js +0 -2
- package/payload/server/public/assets/architecture-YZFGNWBL-Bbnxm4F4.js +0 -1
- package/payload/server/public/assets/browser-B0ieZy-b.js +0 -1
- package/payload/server/public/assets/calendar-CRL2_9Fl.js +0 -1
- package/payload/server/public/assets/channel-CatPTq-5.js +0 -1
- package/payload/server/public/assets/chat-C56bmC6C.js +0 -1
- package/payload/server/public/assets/chevron-left-B2DKUxLk.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-CqLMwOdA.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-CjWy8NJ7.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-DHhR5rdN.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DH4pAdfu.js +0 -1
- package/payload/server/public/assets/clone-DCKzwjWW.js +0 -1
- package/payload/server/public/assets/data-C1ftMulP.js +0 -1
- package/payload/server/public/assets/file-download-CHTyUQqS.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-Ps5HDzLh.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-gtlpwIig.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-CPrWlrsa.js +0 -2
- package/payload/server/public/assets/operator-B4wN2c53.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-DrSn1e0n.js +0 -1
- package/payload/server/public/assets/page-BIfOKi9I.js +0 -32
- package/payload/server/public/assets/page-C1G57kPZ.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-C09i6N-g.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-CMZN2KQH.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BdgkPHuh.js +0 -1
- package/payload/server/public/assets/tasks-0OcRiBdQ.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-CeuUM5oL.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-C--fAaJv.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-CpfVOO26.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-Bo7bnFtC.js +0 -9
- package/payload/server/public/assets/wardley-RL74JXVD-4WPJ2UA9.js +0 -1
- /package/payload/server/public/assets/{_baseFor-Q4DeIqQC.js → _baseFor-D3BqAOBr.js} +0 -0
- /package/payload/server/public/assets/{array-WaOTgZu7.js → array-iYP9fzJp.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-CMmjo4hO.js → cytoscape.esm-BQSBzPsB.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-BxqJVxq5.js → defaultLocale-BrdA1gDi.js} +0 -0
- /package/payload/server/public/assets/{dist-Dx-cpU53.js → dist-Cvgxm7qv.js} +0 -0
- /package/payload/server/public/assets/{init-DX7c5Edh.js → init-Bx0S6pkp.js} +0 -0
- /package/payload/server/public/assets/{katex-B2dtGfSp.js → katex-BsiH_a6d.js} +0 -0
- /package/payload/server/public/assets/{path-CnSyroar.js → path-BLSgTy3w.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-DqboRNgS.js → preload-helper-ClBMtM1g.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-eLccZ4OJ.js → rough.esm-BMOtDaaS.js} +0 -0
- /package/payload/server/public/assets/{src-Dqs1wlnb.js → src-DV4LKv2E.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAYvD;AAOD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EAAE,EACxB,eAAe,GAAE,MAA4B,GAC5C,UAAU,EAAE,CAgBd;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,UAAU,EAAE,EACnB,GAAG,GAAE,MAA2B,GAC/B,MAAM,CAIR;AAED,UAAU,cAAc;IACtB,GAAG,EAAE,CACH,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACvB,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/D;AAOD,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAYvD;AAOD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EAAE,EACxB,eAAe,GAAE,MAA4B,GAC5C,UAAU,EAAE,CAgBd;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,UAAU,EAAE,EACnB,GAAG,GAAE,MAA2B,GAC/B,MAAM,CAIR;AAED,UAAU,cAAc;IACtB,GAAG,EAAE,CACH,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACvB,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/D;AAMD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;AACpE,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,aAAa,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAID,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,eAAe,CAAC;CACzB;AAOD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB;AAoED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,EAAE,CAAC,CAE1B;AAGD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAA2B,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAG/B;AAID,wBAAsB,aAAa,CACjC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAA2B,GAC/B,OAAO,CAAC,UAAU,EAAE,CAAC,CAEvB"}
|
|
@@ -9,7 +9,9 @@ exports.ACTIVE_CANDIDATE_LIMIT = exports.ACTIVE_CANDIDATE_FLOOR = exports.INJECT
|
|
|
9
9
|
exports.cosine = cosine;
|
|
10
10
|
exports.deconflictBySubject = deconflictBySubject;
|
|
11
11
|
exports.formatStandingRulesBlock = formatStandingRulesBlock;
|
|
12
|
+
exports.resolveOwnerUserId = resolveOwnerUserId;
|
|
12
13
|
exports.queryActiveRuleCandidates = queryActiveRuleCandidates;
|
|
14
|
+
exports.resolveActiveRules = resolveActiveRules;
|
|
13
15
|
exports.activeRuleSet = activeRuleSet;
|
|
14
16
|
exports.SAME_SUBJECT_COSINE = 0.85;
|
|
15
17
|
exports.INJECTION_RULE_CAP = 12;
|
|
@@ -55,19 +57,36 @@ function formatStandingRulesBlock(rules, cap = exports.INJECTION_RULE_CAP) {
|
|
|
55
57
|
const lines = rules.slice(0, cap).map((r) => `- ${r.value}`);
|
|
56
58
|
return `## Standing rules\n${lines.join("\n")}`;
|
|
57
59
|
}
|
|
58
|
-
// The
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
60
|
+
// The account's owner identity (Task 1461). One `AdminUser {role:'owner'}` is
|
|
61
|
+
// seeded per account (Task 1359); `null` when absent (a pre-seeding legacy
|
|
62
|
+
// account). Mirrors the memory plugin's resolve-owner-userid.ts, but takes a
|
|
63
|
+
// session so this lib stays dependency-free (no neo4j-driver) — the same
|
|
64
|
+
// cross-process lockstep as the duplicated literals elsewhere in this tree.
|
|
65
|
+
async function resolveOwnerUserId(session, accountId) {
|
|
66
|
+
const res = await session.run(`
|
|
67
|
+
MATCH (au:AdminUser {accountId: $accountId, role: 'owner'})
|
|
68
|
+
RETURN au.userId AS userId
|
|
69
|
+
ORDER BY au.createdAt ASC
|
|
70
|
+
LIMIT 1
|
|
71
|
+
`, { accountId });
|
|
72
|
+
const rec = res.records[0];
|
|
73
|
+
const userId = rec ? rec.get("userId") : null;
|
|
74
|
+
return typeof userId === "string" && userId.length > 0 ? userId : null;
|
|
75
|
+
}
|
|
76
|
+
// The owner's admin-scope candidates, selected through the owner's
|
|
77
|
+
// `UserProfile` and pinned to the resolved owner userId so the prefs selected
|
|
78
|
+
// and the owner logged are one identity. Not trashed, not a "does not apply"
|
|
79
|
+
// declination, above the injection floor, ordered so the highest-confidence /
|
|
80
|
+
// most-recent wins de-confliction. The trashed predicate mirrors graph-trash's
|
|
62
81
|
// `notTrashed()` exactly (label + deletedAt) so this lib stays dependency-free.
|
|
63
|
-
async function
|
|
82
|
+
async function queryOwnerCandidates(session, accountId, ownerUserId) {
|
|
64
83
|
// ACTIVE_CANDIDATE_LIMIT is inlined as a Cypher literal rather than bound as a
|
|
65
84
|
// param: a plain JS number bound to `LIMIT $p` serializes as a FLOAT and Neo4j
|
|
66
85
|
// rejects it ("not a valid value. Must be a non-negative integer"). This lib
|
|
67
86
|
// is dependency-free (no neo4j-driver), so it cannot call `neo4j.int()`; the
|
|
68
87
|
// constant is a hardcoded integer, so inlining it is safe and gate-clean.
|
|
69
88
|
const result = await session.run(`
|
|
70
|
-
MATCH (
|
|
89
|
+
MATCH (up:UserProfile {accountId: $accountId, userId: $ownerUserId})-[:HAS_PREFERENCE]->(pref:Preference {scope: 'admin'})
|
|
71
90
|
WHERE NOT pref:Trashed AND pref.deletedAt IS NULL
|
|
72
91
|
AND coalesce(pref.notApplicable, false) = false
|
|
73
92
|
AND pref.confidence >= $floor
|
|
@@ -76,7 +95,7 @@ async function queryActiveRuleCandidates(session, accountId) {
|
|
|
76
95
|
pref.observedAt AS observedAt, pref.embedding AS embedding
|
|
77
96
|
ORDER BY pref.confidence DESC, pref.observedAt DESC
|
|
78
97
|
LIMIT ${exports.ACTIVE_CANDIDATE_LIMIT}
|
|
79
|
-
`, { accountId, floor: exports.ACTIVE_CANDIDATE_FLOOR });
|
|
98
|
+
`, { accountId, ownerUserId, floor: exports.ACTIVE_CANDIDATE_FLOOR });
|
|
80
99
|
return result.records.map((r) => ({
|
|
81
100
|
preferenceId: r.get("preferenceId"),
|
|
82
101
|
category: r.get("category"),
|
|
@@ -87,8 +106,36 @@ async function queryActiveRuleCandidates(session, accountId) {
|
|
|
87
106
|
embedding: r.get("embedding") ?? null,
|
|
88
107
|
}));
|
|
89
108
|
}
|
|
109
|
+
// Resolve the owner then select. Injection has exactly one selection rule — the
|
|
110
|
+
// owner's prefs. No owner (or an owner-resolution error) yields no candidates
|
|
111
|
+
// rather than falling back to a different selection key. An owner-resolution
|
|
112
|
+
// error is caught here and degrades to empty; it never throws.
|
|
113
|
+
async function resolveCandidates(session, accountId) {
|
|
114
|
+
let ownerUserId;
|
|
115
|
+
try {
|
|
116
|
+
ownerUserId = await resolveOwnerUserId(session, accountId);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return { candidates: [], ownerUserId: null, source: "owner-error" };
|
|
120
|
+
}
|
|
121
|
+
if (!ownerUserId)
|
|
122
|
+
return { candidates: [], ownerUserId: null, source: "no-owner" };
|
|
123
|
+
const candidates = await queryOwnerCandidates(session, accountId, ownerUserId);
|
|
124
|
+
return { candidates, ownerUserId, source: "owner" };
|
|
125
|
+
}
|
|
126
|
+
// Owner-scoped candidates for a downstream reader that only needs the rows
|
|
127
|
+
// (the standing preference-reconciliation audit). Signature unchanged.
|
|
128
|
+
async function queryActiveRuleCandidates(session, accountId) {
|
|
129
|
+
return (await resolveCandidates(session, accountId)).candidates;
|
|
130
|
+
}
|
|
131
|
+
// The account's active, de-conflicted, bounded rule-set plus its provenance.
|
|
132
|
+
async function resolveActiveRules(session, accountId, cap = exports.INJECTION_RULE_CAP) {
|
|
133
|
+
const { candidates, ownerUserId, source } = await resolveCandidates(session, accountId);
|
|
134
|
+
return { rules: deconflictBySubject(candidates).slice(0, cap), ownerUserId, source };
|
|
135
|
+
}
|
|
136
|
+
// The rule array alone — the unchanged call boundary for profile-read and the
|
|
137
|
+
// ui/server injection wrapper.
|
|
90
138
|
async function activeRuleSet(session, accountId, cap = exports.INJECTION_RULE_CAP) {
|
|
91
|
-
|
|
92
|
-
return deconflictBySubject(candidates).slice(0, cap);
|
|
139
|
+
return (await resolveActiveRules(session, accountId, cap)).rules;
|
|
93
140
|
}
|
|
94
141
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,uEAAuE;AACvE,sEAAsE;AACtE,gFAAgF;AAChF,8EAA8E;AAC9E,cAAc;;;AA0Bd,wBAYC;AAOD,kDAmBC;AAED,4DAOC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,uEAAuE;AACvE,sEAAsE;AACtE,gFAAgF;AAChF,8EAA8E;AAC9E,cAAc;;;AA0Bd,wBAYC;AAOD,kDAmBC;AAED,4DAOC;AAmCD,gDAgBC;AAoED,8DAKC;AAGD,gDAOC;AAID,sCAMC;AAvNY,QAAA,mBAAmB,GAAG,IAAI,CAAC;AAC3B,QAAA,kBAAkB,GAAG,EAAE,CAAC;AACxB,QAAA,sBAAsB,GAAG,GAAG,CAAC;AAC7B,QAAA,sBAAsB,GAAG,EAAE,CAAC;AAqBzC,SAAgB,MAAM,CAAC,CAAW,EAAE,CAAW;IAC7C,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IAC9D,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAClB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IACD,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACnC,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,0EAA0E;AAC1E,uEAAuE;AACvE,8EAA8E;AAC9E,gFAAgF;AAChF,mBAAmB;AACnB,SAAgB,mBAAmB,CACjC,OAAwB,EACxB,kBAA0B,2BAAmB;IAE7C,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC;QACxB,MAAM,KAAK,GACT,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAClB,GAAG,CAAC,MAAM,GAAG,CAAC;YACd,OAAO,CAAC,IAAI,CACV,CAAC,CAAC,EAAE,EAAE,CACJ,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC1B,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;gBACtB,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,eAAe,CAC9C,CAAC;QACJ,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAED,SAAgB,wBAAwB,CACtC,KAAmB,EACnB,MAAc,0BAAkB;IAEhC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IAC7D,OAAO,sBAAsB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAClD,CAAC;AA8BD,8EAA8E;AAC9E,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AACrE,KAAK,UAAU,kBAAkB,CACtC,OAAuB,EACvB,SAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAC3B;;;;;KAKC,EACD,EAAE,SAAS,EAAE,CACd,CAAC;IACF,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACzE,CAAC;AAED,mEAAmE;AACnE,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,gFAAgF;AAChF,KAAK,UAAU,oBAAoB,CACjC,OAAuB,EACvB,SAAiB,EACjB,WAAmB;IAEnB,+EAA+E;IAC/E,+EAA+E;IAC/E,6EAA6E;IAC7E,6EAA6E;IAC7E,0EAA0E;IAC1E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B;;;;;;;;;YASQ,8BAAsB;KAC7B,EACD,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,8BAAsB,EAAE,CAC1D,CAAC;IACF,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChC,YAAY,EAAE,CAAC,CAAC,GAAG,CAAC,cAAc,CAAW;QAC7C,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAW;QACrC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAW;QAC3B,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAW;QAC/B,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,YAAY,CAAW;QACzC,UAAU,EAAG,CAAC,CAAC,GAAG,CAAC,YAAY,CAAY,IAAI,EAAE;QACjD,SAAS,EAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAqB,IAAI,IAAI;KAC3D,CAAC,CAAC,CAAC;AACN,CAAC;AAED,gFAAgF;AAChF,8EAA8E;AAC9E,6EAA6E;AAC7E,+DAA+D;AAC/D,KAAK,UAAU,iBAAiB,CAC9B,OAAuB,EACvB,SAAiB;IAMjB,IAAI,WAA0B,CAAC;IAC/B,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,kBAAkB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACtE,CAAC;IACD,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACnF,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAC/E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACtD,CAAC;AAED,2EAA2E;AAC3E,uEAAuE;AAChE,KAAK,UAAU,yBAAyB,CAC7C,OAAuB,EACvB,SAAiB;IAEjB,OAAO,CAAC,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;AAClE,CAAC;AAED,6EAA6E;AACtE,KAAK,UAAU,kBAAkB,CACtC,OAAuB,EACvB,SAAiB,EACjB,MAAc,0BAAkB;IAEhC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACxF,OAAO,EAAE,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AACvF,CAAC;AAED,8EAA8E;AAC9E,+BAA+B;AACxB,KAAK,UAAU,aAAa,CACjC,OAAuB,EACvB,SAAiB,EACjB,MAAc,0BAAkB;IAEhC,OAAO,CAAC,MAAM,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AACnE,CAAC"}
|
|
@@ -3,6 +3,9 @@ import {
|
|
|
3
3
|
cosine,
|
|
4
4
|
deconflictBySubject,
|
|
5
5
|
formatStandingRulesBlock,
|
|
6
|
+
resolveActiveRules,
|
|
7
|
+
activeRuleSet,
|
|
8
|
+
queryActiveRuleCandidates,
|
|
6
9
|
INJECTION_RULE_CAP,
|
|
7
10
|
type RuleCandidate,
|
|
8
11
|
} from "./index.js";
|
|
@@ -68,6 +71,109 @@ describe("deconflictBySubject", () => {
|
|
|
68
71
|
});
|
|
69
72
|
});
|
|
70
73
|
|
|
74
|
+
// A fake Neo4j session that dispatches on query text: the owner-resolution
|
|
75
|
+
// query (matches `role: 'owner'`) returns a configurable owner userId or none;
|
|
76
|
+
// the candidate query (matches HAS_PREFERENCE) returns configurable pref rows
|
|
77
|
+
// and asserts it was pinned to the resolved owner userId.
|
|
78
|
+
function fakeSession(opts: {
|
|
79
|
+
ownerId?: string | null;
|
|
80
|
+
ownerThrows?: boolean;
|
|
81
|
+
prefRows?: Array<Record<string, unknown>>;
|
|
82
|
+
}) {
|
|
83
|
+
return {
|
|
84
|
+
calls: [] as string[],
|
|
85
|
+
candidateRuns: 0,
|
|
86
|
+
async run(q: string, p: Record<string, unknown>) {
|
|
87
|
+
this.calls.push(q);
|
|
88
|
+
if (/role:\s*'owner'/.test(q)) {
|
|
89
|
+
if (opts.ownerThrows) throw new Error("neo4j down");
|
|
90
|
+
const recs = opts.ownerId
|
|
91
|
+
? [{ get: (_k: string) => opts.ownerId }]
|
|
92
|
+
: [];
|
|
93
|
+
return { records: recs };
|
|
94
|
+
}
|
|
95
|
+
// candidate query — must be pinned to the resolved owner userId
|
|
96
|
+
this.candidateRuns++;
|
|
97
|
+
expect(p.ownerUserId).toBe(opts.ownerId);
|
|
98
|
+
return {
|
|
99
|
+
records: (opts.prefRows ?? []).map((r) => ({
|
|
100
|
+
get: (k: string) => r[k],
|
|
101
|
+
})),
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const prefRow = (over: Partial<RuleCandidate>): Record<string, unknown> => ({
|
|
108
|
+
preferenceId: "p",
|
|
109
|
+
category: "communication",
|
|
110
|
+
key: "k",
|
|
111
|
+
value: "v",
|
|
112
|
+
confidence: 0.6,
|
|
113
|
+
observedAt: "2026-07-01T00:00:00Z",
|
|
114
|
+
embedding: null,
|
|
115
|
+
...over,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe("resolveActiveRules — owner-scoped selection", () => {
|
|
119
|
+
it("returns the owner's prefs with source=owner when an owner exists", async () => {
|
|
120
|
+
const s = fakeSession({
|
|
121
|
+
ownerId: "owner-35fed05e",
|
|
122
|
+
prefRows: [
|
|
123
|
+
prefRow({ preferenceId: "a", value: "brand", confidence: 0.9 }),
|
|
124
|
+
prefRow({ preferenceId: "b", value: "pricing", confidence: 0.7 }),
|
|
125
|
+
prefRow({ preferenceId: "c", value: "tender", confidence: 0.5 }),
|
|
126
|
+
],
|
|
127
|
+
});
|
|
128
|
+
const res = await resolveActiveRules(s, "acct-1");
|
|
129
|
+
expect(res.source).toBe("owner");
|
|
130
|
+
expect(res.ownerUserId).toBe("owner-35fed05e");
|
|
131
|
+
expect(res.rules.map((r) => r.preferenceId)).toEqual(["a", "b", "c"]);
|
|
132
|
+
expect(s.candidateRuns).toBe(1);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("returns empty with source=no-owner and never runs the candidate query", async () => {
|
|
136
|
+
const s = fakeSession({ ownerId: null });
|
|
137
|
+
const res = await resolveActiveRules(s, "acct-1");
|
|
138
|
+
expect(res.source).toBe("no-owner");
|
|
139
|
+
expect(res.ownerUserId).toBeNull();
|
|
140
|
+
expect(res.rules).toEqual([]);
|
|
141
|
+
expect(s.candidateRuns).toBe(0);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("returns empty with source=owner when the owner has zero prefs", async () => {
|
|
145
|
+
const s = fakeSession({ ownerId: "owner-x", prefRows: [] });
|
|
146
|
+
const res = await resolveActiveRules(s, "acct-1");
|
|
147
|
+
expect(res.source).toBe("owner");
|
|
148
|
+
expect(res.ownerUserId).toBe("owner-x");
|
|
149
|
+
expect(res.rules).toEqual([]);
|
|
150
|
+
expect(s.candidateRuns).toBe(1);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("degrades to empty with source=owner-error on an owner-resolution failure (never throws)", async () => {
|
|
154
|
+
const s = fakeSession({ ownerThrows: true });
|
|
155
|
+
const res = await resolveActiveRules(s, "acct-1");
|
|
156
|
+
expect(res.source).toBe("owner-error");
|
|
157
|
+
expect(res.ownerUserId).toBeNull();
|
|
158
|
+
expect(res.rules).toEqual([]);
|
|
159
|
+
expect(s.candidateRuns).toBe(0);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("activeRuleSet returns just the owner's rule array", async () => {
|
|
163
|
+
const s = fakeSession({
|
|
164
|
+
ownerId: "owner-1",
|
|
165
|
+
prefRows: [prefRow({ preferenceId: "a" })],
|
|
166
|
+
});
|
|
167
|
+
const rules = await activeRuleSet(s, "acct-1");
|
|
168
|
+
expect(rules.map((r) => r.preferenceId)).toEqual(["a"]);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("queryActiveRuleCandidates stays owner-scoped (empty on no owner)", async () => {
|
|
172
|
+
const s = fakeSession({ ownerId: null });
|
|
173
|
+
expect(await queryActiveRuleCandidates(s, "acct-1")).toEqual([]);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
71
177
|
describe("formatStandingRulesBlock", () => {
|
|
72
178
|
it("returns empty string for no rules", () => {
|
|
73
179
|
expect(formatStandingRulesBlock([], INJECTION_RULE_CAP)).toBe("");
|
|
@@ -84,14 +84,60 @@ interface MinimalSession {
|
|
|
84
84
|
) => Promise<{ records: Array<{ get(k: string): unknown }> }>;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
// the
|
|
87
|
+
// Task 1564 — which admin `AdminUser`/`UserProfile` owns a preference now
|
|
88
|
+
// decides whether it is injected. `source` records how the rule-set was
|
|
89
|
+
// selected; `InjectionSource` widens it with `fetch-error`, produced only by
|
|
90
|
+
// the ui/server never-throw catch (a hard Neo4j failure), never by this lib.
|
|
91
|
+
export type ActiveRuleSource = "owner" | "no-owner" | "owner-error";
|
|
92
|
+
export type InjectionSource = ActiveRuleSource | "fetch-error";
|
|
93
|
+
|
|
94
|
+
export interface ActiveRuleResolution {
|
|
95
|
+
rules: ActiveRule[];
|
|
96
|
+
ownerUserId: string | null;
|
|
97
|
+
source: ActiveRuleSource;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// The per-turn injection payload the UI hands each channel gateway: the
|
|
101
|
+
// formatted `## Standing rules` block plus the provenance the gateway logs.
|
|
102
|
+
export interface StandingRulesInjection {
|
|
103
|
+
block: string;
|
|
104
|
+
ownerUserId: string | null;
|
|
105
|
+
source: InjectionSource;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// The account's owner identity (Task 1461). One `AdminUser {role:'owner'}` is
|
|
109
|
+
// seeded per account (Task 1359); `null` when absent (a pre-seeding legacy
|
|
110
|
+
// account). Mirrors the memory plugin's resolve-owner-userid.ts, but takes a
|
|
111
|
+
// session so this lib stays dependency-free (no neo4j-driver) — the same
|
|
112
|
+
// cross-process lockstep as the duplicated literals elsewhere in this tree.
|
|
113
|
+
export async function resolveOwnerUserId(
|
|
114
|
+
session: MinimalSession,
|
|
115
|
+
accountId: string,
|
|
116
|
+
): Promise<string | null> {
|
|
117
|
+
const res = await session.run(
|
|
118
|
+
`
|
|
119
|
+
MATCH (au:AdminUser {accountId: $accountId, role: 'owner'})
|
|
120
|
+
RETURN au.userId AS userId
|
|
121
|
+
ORDER BY au.createdAt ASC
|
|
122
|
+
LIMIT 1
|
|
123
|
+
`,
|
|
124
|
+
{ accountId },
|
|
125
|
+
);
|
|
126
|
+
const rec = res.records[0];
|
|
127
|
+
const userId = rec ? rec.get("userId") : null;
|
|
128
|
+
return typeof userId === "string" && userId.length > 0 ? userId : null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// The owner's admin-scope candidates, selected through the owner's
|
|
132
|
+
// `UserProfile` and pinned to the resolved owner userId so the prefs selected
|
|
133
|
+
// and the owner logged are one identity. Not trashed, not a "does not apply"
|
|
134
|
+
// declination, above the injection floor, ordered so the highest-confidence /
|
|
135
|
+
// most-recent wins de-confliction. The trashed predicate mirrors graph-trash's
|
|
91
136
|
// `notTrashed()` exactly (label + deletedAt) so this lib stays dependency-free.
|
|
92
|
-
|
|
137
|
+
async function queryOwnerCandidates(
|
|
93
138
|
session: MinimalSession,
|
|
94
139
|
accountId: string,
|
|
140
|
+
ownerUserId: string,
|
|
95
141
|
): Promise<RuleCandidate[]> {
|
|
96
142
|
// ACTIVE_CANDIDATE_LIMIT is inlined as a Cypher literal rather than bound as a
|
|
97
143
|
// param: a plain JS number bound to `LIMIT $p` serializes as a FLOAT and Neo4j
|
|
@@ -100,7 +146,7 @@ export async function queryActiveRuleCandidates(
|
|
|
100
146
|
// constant is a hardcoded integer, so inlining it is safe and gate-clean.
|
|
101
147
|
const result = await session.run(
|
|
102
148
|
`
|
|
103
|
-
MATCH (
|
|
149
|
+
MATCH (up:UserProfile {accountId: $accountId, userId: $ownerUserId})-[:HAS_PREFERENCE]->(pref:Preference {scope: 'admin'})
|
|
104
150
|
WHERE NOT pref:Trashed AND pref.deletedAt IS NULL
|
|
105
151
|
AND coalesce(pref.notApplicable, false) = false
|
|
106
152
|
AND pref.confidence >= $floor
|
|
@@ -110,7 +156,7 @@ export async function queryActiveRuleCandidates(
|
|
|
110
156
|
ORDER BY pref.confidence DESC, pref.observedAt DESC
|
|
111
157
|
LIMIT ${ACTIVE_CANDIDATE_LIMIT}
|
|
112
158
|
`,
|
|
113
|
-
{ accountId, floor: ACTIVE_CANDIDATE_FLOOR },
|
|
159
|
+
{ accountId, ownerUserId, floor: ACTIVE_CANDIDATE_FLOOR },
|
|
114
160
|
);
|
|
115
161
|
return result.records.map((r) => ({
|
|
116
162
|
preferenceId: r.get("preferenceId") as string,
|
|
@@ -123,11 +169,54 @@ export async function queryActiveRuleCandidates(
|
|
|
123
169
|
}));
|
|
124
170
|
}
|
|
125
171
|
|
|
172
|
+
// Resolve the owner then select. Injection has exactly one selection rule — the
|
|
173
|
+
// owner's prefs. No owner (or an owner-resolution error) yields no candidates
|
|
174
|
+
// rather than falling back to a different selection key. An owner-resolution
|
|
175
|
+
// error is caught here and degrades to empty; it never throws.
|
|
176
|
+
async function resolveCandidates(
|
|
177
|
+
session: MinimalSession,
|
|
178
|
+
accountId: string,
|
|
179
|
+
): Promise<{
|
|
180
|
+
candidates: RuleCandidate[];
|
|
181
|
+
ownerUserId: string | null;
|
|
182
|
+
source: ActiveRuleSource;
|
|
183
|
+
}> {
|
|
184
|
+
let ownerUserId: string | null;
|
|
185
|
+
try {
|
|
186
|
+
ownerUserId = await resolveOwnerUserId(session, accountId);
|
|
187
|
+
} catch {
|
|
188
|
+
return { candidates: [], ownerUserId: null, source: "owner-error" };
|
|
189
|
+
}
|
|
190
|
+
if (!ownerUserId) return { candidates: [], ownerUserId: null, source: "no-owner" };
|
|
191
|
+
const candidates = await queryOwnerCandidates(session, accountId, ownerUserId);
|
|
192
|
+
return { candidates, ownerUserId, source: "owner" };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Owner-scoped candidates for a downstream reader that only needs the rows
|
|
196
|
+
// (the standing preference-reconciliation audit). Signature unchanged.
|
|
197
|
+
export async function queryActiveRuleCandidates(
|
|
198
|
+
session: MinimalSession,
|
|
199
|
+
accountId: string,
|
|
200
|
+
): Promise<RuleCandidate[]> {
|
|
201
|
+
return (await resolveCandidates(session, accountId)).candidates;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// The account's active, de-conflicted, bounded rule-set plus its provenance.
|
|
205
|
+
export async function resolveActiveRules(
|
|
206
|
+
session: MinimalSession,
|
|
207
|
+
accountId: string,
|
|
208
|
+
cap: number = INJECTION_RULE_CAP,
|
|
209
|
+
): Promise<ActiveRuleResolution> {
|
|
210
|
+
const { candidates, ownerUserId, source } = await resolveCandidates(session, accountId);
|
|
211
|
+
return { rules: deconflictBySubject(candidates).slice(0, cap), ownerUserId, source };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// The rule array alone — the unchanged call boundary for profile-read and the
|
|
215
|
+
// ui/server injection wrapper.
|
|
126
216
|
export async function activeRuleSet(
|
|
127
217
|
session: MinimalSession,
|
|
128
218
|
accountId: string,
|
|
129
219
|
cap: number = INJECTION_RULE_CAP,
|
|
130
220
|
): Promise<ActiveRule[]> {
|
|
131
|
-
|
|
132
|
-
return deconflictBySubject(candidates).slice(0, cap);
|
|
221
|
+
return (await resolveActiveRules(session, accountId, cap)).rules;
|
|
133
222
|
}
|
|
@@ -6,5 +6,5 @@ export declare const EMBED_REQUEST_TIMEOUT_MS: number;
|
|
|
6
6
|
export declare const EMBED_KEEP_ALIVE: number | string;
|
|
7
7
|
export declare function embed(text: string): Promise<number[]>;
|
|
8
8
|
export declare function subBatchCharBudget(msPerChar: number): number;
|
|
9
|
-
export declare function embedBatch(texts: string[]): Promise<number[][]>;
|
|
9
|
+
export declare function embedBatch(texts: string[], onProgress?: (done: number, total: number) => void): Promise<number[][]>;
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,qBAAqB,QASjC,CAAC;AA0BF,eAAO,MAAM,mBAAmB,QAA4D,CAAC;AAC7F,eAAO,MAAM,0BAA0B,QAGtC,CAAC;AAWF,eAAO,MAAM,kBAAkB,QAA8D,CAAC;AAY9F,eAAO,MAAM,wBAAwB,QAGpC,CAAC;AAcF,eAAO,MAAM,gBAAgB,EAAE,MAAM,GAAG,MAEhB,CAAC;AA0FzB,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAG3D;AAcD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAM5D;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EAAE,EAQf,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACjD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAuDrB"}
|
|
@@ -19,17 +19,18 @@ function envInt(name, def) {
|
|
|
19
19
|
const n = Number(raw);
|
|
20
20
|
return Number.isFinite(n) ? n : def;
|
|
21
21
|
}
|
|
22
|
-
// nomic-embed-text's usable embed context is 2048 tokens. The
|
|
23
|
-
// assumed ~4 chars/token
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
22
|
+
// nomic-embed-text's usable embed context is 2048 tokens. The cap has been
|
|
23
|
+
// tightened twice against real 400s: 8000 (assumed ~4 chars/token) still
|
|
24
|
+
// overflowed on dense emoji/markup, then 6000 (~3 chars/token) still 400'd on
|
|
25
|
+
// the densest sections with "input length exceeds the context length" because
|
|
26
|
+
// that content runs closer to ~2 chars/token. Size the default against a
|
|
27
|
+
// conservative 2 chars/token worst case, reserving a small token margin for the
|
|
28
|
+
// tokenizer's specials, so a capped input is provably under context:
|
|
29
|
+
// (2048 - 48) * 2 = 4000 (Task 1558). Context is env-overridable so raising it
|
|
30
|
+
// raises the cap; EMBED_INPUT_MAX_CHARS is also directly overridable.
|
|
30
31
|
const EMBED_MODEL_CONTEXT_TOKENS = Math.max(1, Math.floor(envInt("EMBED_MODEL_CONTEXT_TOKENS", 2048)));
|
|
31
32
|
const EMBED_CONTEXT_MARGIN_TOKENS = 48;
|
|
32
|
-
const EMBED_WORST_CASE_CHARS_PER_TOKEN =
|
|
33
|
+
const EMBED_WORST_CASE_CHARS_PER_TOKEN = 2;
|
|
33
34
|
exports.EMBED_INPUT_MAX_CHARS = Math.max(1, Math.floor(envInt("EMBED_INPUT_MAX_CHARS", (EMBED_MODEL_CONTEXT_TOKENS - EMBED_CONTEXT_MARGIN_TOKENS) *
|
|
34
35
|
EMBED_WORST_CASE_CHARS_PER_TOKEN)));
|
|
35
36
|
// Batch pacing (Task 960). On a passively-cooled Pi, embedding a whole
|
|
@@ -43,7 +44,20 @@ exports.EMBED_INPUT_MAX_CHARS = Math.max(1, Math.floor(envInt("EMBED_INPUT_MAX_C
|
|
|
43
44
|
// this pacing is defence-in-depth and faster recovery. Both knobs are
|
|
44
45
|
// env-overridable so an operator can tune them from on-device thermal
|
|
45
46
|
// measurement without a code change.
|
|
46
|
-
|
|
47
|
+
//
|
|
48
|
+
// Count ceiling after adaptive sizing (Task 1558). Since Task 1553 each POST is
|
|
49
|
+
// sized by a character budget derived from the device's *measured* ms-per-char,
|
|
50
|
+
// so EMBED_SUBBATCH_SIZE is no longer the primary timeout guard — it is the hard
|
|
51
|
+
// count cap layered on top. It still matters for the one case the char budget
|
|
52
|
+
// cannot catch: the budget is derived from the probe's observed rate, so if the
|
|
53
|
+
// probe runs while the machine is briefly quiet the budget is large and the next
|
|
54
|
+
// POST packs up to this ceiling; if desktop contention then spikes mid-batch,
|
|
55
|
+
// that POST runs far slower than measured and can blow EMBED_REQUEST_TIMEOUT_MS.
|
|
56
|
+
// A ceiling of 4 bounds that worst case (~4 x 17s cold-CPU embeds on a contended
|
|
57
|
+
// shared desktop ~= 68s, under the 120s timeout) so a fast-probe-then-contention
|
|
58
|
+
// batch still fits. On a quiet dedicated appliance (a Pi) the char budget, not
|
|
59
|
+
// this count, is the binding constraint.
|
|
60
|
+
exports.EMBED_SUBBATCH_SIZE = Math.max(1, Math.floor(envInt("EMBED_SUBBATCH_SIZE", 4)));
|
|
47
61
|
exports.EMBED_SUBBATCH_COOLDOWN_MS = Math.max(0, envInt("EMBED_SUBBATCH_COOLDOWN_MS", 1000));
|
|
48
62
|
// Drift baseline (Task 1553). This was Task 1533's sizing driver — the budgeted
|
|
49
63
|
// worst-case wall-time for one capped input — but sizing that from a single
|
|
@@ -171,12 +185,23 @@ function subBatchCharBudget(msPerChar) {
|
|
|
171
185
|
const perChar = Math.max(msPerChar, Number.MIN_VALUE); // guard div-by-zero
|
|
172
186
|
return Math.max(1, Math.floor((exports.EMBED_REQUEST_TIMEOUT_MS * EMBED_TIMEOUT_UTILISATION) / perChar));
|
|
173
187
|
}
|
|
174
|
-
async function embedBatch(texts
|
|
188
|
+
async function embedBatch(texts,
|
|
189
|
+
// Progress callback (Task 1555). Fired after each sub-batch POST resolves
|
|
190
|
+
// with (done, total): done = cumulative inputs embedded so far, total =
|
|
191
|
+
// inputs.length. memory-ingest passes a callback that emits an MCP progress
|
|
192
|
+
// notification per POST, which resets Claude Code's ~30-minute stdio idle
|
|
193
|
+
// timer so a long single ingest is not aborted mid-write. Kept MCP-agnostic
|
|
194
|
+
// — a plain (done, total) callback — so embed-client carries no MCP concepts
|
|
195
|
+
// and every existing one-arg caller is unchanged.
|
|
196
|
+
onProgress) {
|
|
175
197
|
const inputs = texts.map(capInput);
|
|
176
198
|
// 0 or 1 input is exactly one POST: the warm interactive query path is
|
|
177
|
-
// unaffected, and the empty-array behaviour is unchanged.
|
|
199
|
+
// unaffected, and the empty-array behaviour is unchanged. Report once so the
|
|
200
|
+
// callback contract ("fires after every POST") holds on this path too.
|
|
178
201
|
if (inputs.length <= 1) {
|
|
179
|
-
|
|
202
|
+
const vectors = await postBatch(inputs);
|
|
203
|
+
onProgress?.(inputs.length, inputs.length);
|
|
204
|
+
return vectors;
|
|
180
205
|
}
|
|
181
206
|
// Measure-and-size. Probe with one input, then pack each subsequent POST with
|
|
182
207
|
// as many inputs as fit the character budget derived from the worst
|
|
@@ -213,6 +238,10 @@ async function embedBatch(texts) {
|
|
|
213
238
|
maxMsPerChar === null ? observedMsPerChar : Math.max(maxMsPerChar, observedMsPerChar);
|
|
214
239
|
out.push(...vectors);
|
|
215
240
|
i = end;
|
|
241
|
+
// Report progress after each POST resolves. out.length is the cumulative
|
|
242
|
+
// inputs embedded so far; the final iteration reports out.length ===
|
|
243
|
+
// inputs.length.
|
|
244
|
+
onProgress?.(out.length, inputs.length);
|
|
216
245
|
}
|
|
217
246
|
return out;
|
|
218
247
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,yEAAyE;AACzE,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,+EAA+E;AAC/E,gDAAgD;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,17 +15,18 @@ function envInt(name: string, def: number): number {
|
|
|
15
15
|
return Number.isFinite(n) ? n : def;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
// nomic-embed-text's usable embed context is 2048 tokens. The
|
|
19
|
-
// assumed ~4 chars/token
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
18
|
+
// nomic-embed-text's usable embed context is 2048 tokens. The cap has been
|
|
19
|
+
// tightened twice against real 400s: 8000 (assumed ~4 chars/token) still
|
|
20
|
+
// overflowed on dense emoji/markup, then 6000 (~3 chars/token) still 400'd on
|
|
21
|
+
// the densest sections with "input length exceeds the context length" because
|
|
22
|
+
// that content runs closer to ~2 chars/token. Size the default against a
|
|
23
|
+
// conservative 2 chars/token worst case, reserving a small token margin for the
|
|
24
|
+
// tokenizer's specials, so a capped input is provably under context:
|
|
25
|
+
// (2048 - 48) * 2 = 4000 (Task 1558). Context is env-overridable so raising it
|
|
26
|
+
// raises the cap; EMBED_INPUT_MAX_CHARS is also directly overridable.
|
|
26
27
|
const EMBED_MODEL_CONTEXT_TOKENS = Math.max(1, Math.floor(envInt("EMBED_MODEL_CONTEXT_TOKENS", 2048)));
|
|
27
28
|
const EMBED_CONTEXT_MARGIN_TOKENS = 48;
|
|
28
|
-
const EMBED_WORST_CASE_CHARS_PER_TOKEN =
|
|
29
|
+
const EMBED_WORST_CASE_CHARS_PER_TOKEN = 2;
|
|
29
30
|
export const EMBED_INPUT_MAX_CHARS = Math.max(
|
|
30
31
|
1,
|
|
31
32
|
Math.floor(
|
|
@@ -48,7 +49,20 @@ export const EMBED_INPUT_MAX_CHARS = Math.max(
|
|
|
48
49
|
// this pacing is defence-in-depth and faster recovery. Both knobs are
|
|
49
50
|
// env-overridable so an operator can tune them from on-device thermal
|
|
50
51
|
// measurement without a code change.
|
|
51
|
-
|
|
52
|
+
//
|
|
53
|
+
// Count ceiling after adaptive sizing (Task 1558). Since Task 1553 each POST is
|
|
54
|
+
// sized by a character budget derived from the device's *measured* ms-per-char,
|
|
55
|
+
// so EMBED_SUBBATCH_SIZE is no longer the primary timeout guard — it is the hard
|
|
56
|
+
// count cap layered on top. It still matters for the one case the char budget
|
|
57
|
+
// cannot catch: the budget is derived from the probe's observed rate, so if the
|
|
58
|
+
// probe runs while the machine is briefly quiet the budget is large and the next
|
|
59
|
+
// POST packs up to this ceiling; if desktop contention then spikes mid-batch,
|
|
60
|
+
// that POST runs far slower than measured and can blow EMBED_REQUEST_TIMEOUT_MS.
|
|
61
|
+
// A ceiling of 4 bounds that worst case (~4 x 17s cold-CPU embeds on a contended
|
|
62
|
+
// shared desktop ~= 68s, under the 120s timeout) so a fast-probe-then-contention
|
|
63
|
+
// batch still fits. On a quiet dedicated appliance (a Pi) the char budget, not
|
|
64
|
+
// this count, is the binding constraint.
|
|
65
|
+
export const EMBED_SUBBATCH_SIZE = Math.max(1, Math.floor(envInt("EMBED_SUBBATCH_SIZE", 4)));
|
|
52
66
|
export const EMBED_SUBBATCH_COOLDOWN_MS = Math.max(
|
|
53
67
|
0,
|
|
54
68
|
envInt("EMBED_SUBBATCH_COOLDOWN_MS", 1000),
|
|
@@ -209,13 +223,26 @@ export function subBatchCharBudget(msPerChar: number): number {
|
|
|
209
223
|
);
|
|
210
224
|
}
|
|
211
225
|
|
|
212
|
-
export async function embedBatch(
|
|
226
|
+
export async function embedBatch(
|
|
227
|
+
texts: string[],
|
|
228
|
+
// Progress callback (Task 1555). Fired after each sub-batch POST resolves
|
|
229
|
+
// with (done, total): done = cumulative inputs embedded so far, total =
|
|
230
|
+
// inputs.length. memory-ingest passes a callback that emits an MCP progress
|
|
231
|
+
// notification per POST, which resets Claude Code's ~30-minute stdio idle
|
|
232
|
+
// timer so a long single ingest is not aborted mid-write. Kept MCP-agnostic
|
|
233
|
+
// — a plain (done, total) callback — so embed-client carries no MCP concepts
|
|
234
|
+
// and every existing one-arg caller is unchanged.
|
|
235
|
+
onProgress?: (done: number, total: number) => void,
|
|
236
|
+
): Promise<number[][]> {
|
|
213
237
|
const inputs = texts.map(capInput);
|
|
214
238
|
|
|
215
239
|
// 0 or 1 input is exactly one POST: the warm interactive query path is
|
|
216
|
-
// unaffected, and the empty-array behaviour is unchanged.
|
|
240
|
+
// unaffected, and the empty-array behaviour is unchanged. Report once so the
|
|
241
|
+
// callback contract ("fires after every POST") holds on this path too.
|
|
217
242
|
if (inputs.length <= 1) {
|
|
218
|
-
|
|
243
|
+
const vectors = await postBatch(inputs);
|
|
244
|
+
onProgress?.(inputs.length, inputs.length);
|
|
245
|
+
return vectors;
|
|
219
246
|
}
|
|
220
247
|
|
|
221
248
|
// Measure-and-size. Probe with one input, then pack each subsequent POST with
|
|
@@ -255,6 +282,10 @@ export async function embedBatch(texts: string[]): Promise<number[][]> {
|
|
|
255
282
|
maxMsPerChar === null ? observedMsPerChar : Math.max(maxMsPerChar, observedMsPerChar);
|
|
256
283
|
out.push(...vectors);
|
|
257
284
|
i = end;
|
|
285
|
+
// Report progress after each POST resolves. out.length is the cumulative
|
|
286
|
+
// inputs embedded so far; the final iteration reports out.length ===
|
|
287
|
+
// inputs.length.
|
|
288
|
+
onProgress?.(out.length, inputs.length);
|
|
258
289
|
}
|
|
259
290
|
return out;
|
|
260
291
|
}
|