@rubytech/create-maxy-code 0.1.255 → 0.1.256
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/dist/__tests__/plugin-install.test.js +58 -40
- package/dist/index.js +77 -26
- package/dist/lib/plugin-install.js +31 -29
- package/package.json +1 -1
- package/payload/platform/config/brand-registry.json +8 -0
- package/payload/platform/config/brand.json +3 -3
- package/payload/platform/lib/graph-search/src/__tests__/fulltext-coverage.test.ts +12 -0
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +2 -0
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +2 -0
- package/payload/platform/neo4j/schema.cypher +126 -0
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +3 -6
- package/payload/platform/plugins/admin/mcp/dist/index.js +0 -60
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/insight/SKILL.md +24 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +63 -10
- package/payload/platform/plugins/docs/PLUGIN.md +1 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/plugins/docs/references/deployment.md +18 -5
- package/payload/platform/plugins/docs/references/memory-guide.md +4 -0
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/docs/references/slides.md +31 -0
- package/payload/platform/plugins/docs/references/voice-mirror-guide.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +10 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-construction.md +72 -0
- package/payload/platform/plugins/slides/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/slides/LICENSE +21 -0
- package/payload/platform/plugins/slides/PLUGIN.md +18 -0
- package/payload/platform/plugins/slides/PROVENANCE.md +40 -0
- package/payload/platform/plugins/slides/commands/add-slide.md +29 -0
- package/payload/platform/plugins/slides/commands/slides-claus.md +39 -0
- package/payload/platform/plugins/slides/commands/slides-new-component.md +39 -0
- package/payload/platform/plugins/slides/commands/slides-outline.md +43 -0
- package/payload/platform/plugins/slides/commands/slides-review.md +52 -0
- package/payload/platform/plugins/slides/commands/slides-theme.md +64 -0
- package/payload/platform/plugins/slides/commands/slides.md +59 -0
- package/payload/platform/plugins/slides/skills/deck-system/REFERENCE.md +581 -0
- package/payload/platform/plugins/slides/skills/deck-system/SKILL.md +607 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-board.md +426 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-claus.md +185 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-mbb.md +450 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-product-launch.md +579 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sales.md +464 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sequoia.md +489 -0
- package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING.md +273 -0
- package/payload/platform/plugins/slides/skills/deck-system/deck-craft.html +1371 -0
- package/payload/platform/plugins/slides/skills/deck-system/deck-solid.html +1667 -0
- package/payload/platform/plugins/slides/skills/deck-system/deck.html +1359 -0
- package/payload/platform/plugins/url-get/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/url-get/PLUGIN.md +26 -21
- package/payload/platform/plugins/url-get/mcp/dist/index.js +3 -3
- package/payload/platform/plugins/url-get/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts +1 -2
- package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts.map +1 -1
- package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js +20 -40
- package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js.map +1 -1
- package/payload/platform/scripts/setup-account.sh +1 -10
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +0 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +5 -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 +32 -2
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +2 -2
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
- package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +1 -1
- package/payload/premium-plugins/writer-craft/PLUGIN.md +2 -2
- package/payload/premium-plugins/writer-craft/mcp/dist/index.js +5 -5
- package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts +4 -8
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js +30 -98
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/scripts/smoke.mjs +37 -114
- package/payload/premium-plugins/writer-craft/mcp/src/index.ts +5 -5
- package/payload/premium-plugins/writer-craft/mcp/src/lib/voice-corpus.ts +1 -1
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-ingest-session-text.ts +29 -106
- package/payload/premium-plugins/writer-craft/skills/voice-mirror/SKILL.md +15 -17
- package/payload/server/public/assets/AdminShell-T-YknnBn.js +1 -0
- package/payload/server/public/assets/Checkbox-DmDxpqVv.js +1 -0
- package/payload/server/public/assets/admin-COUV-jgt.js +1 -0
- package/payload/server/public/assets/{arc-aUiRP9AS.js → arc-B2CweJq3.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-Dnn6Hc65.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-c09loTER.js → architectureDiagram-Q4EWVU46-DP2o-MFV.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Cjdeyoq1.js → blockDiagram-DXYQGD6D-DO4mcYDJ.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-NY6Wlzo2.js → c4Diagram-AHTNJAMY-Sy1giHbj.js} +1 -1
- package/payload/server/public/assets/channel-CEpR_0rE.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-BK3470lx.js → chunk-2KRD3SAO-CKsCYCsN.js} +1 -1
- package/payload/server/public/assets/chunk-336JU56O-C0-P-aUF.js +2 -0
- package/payload/server/public/assets/chunk-426QAEUC-DFjEt3Zb.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-BOvVdJLf.js → chunk-4BX2VUAB-B8bqAmBa.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BXpto3yW.js → chunk-4TB4RGXK-D1k0VSlW.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-BwZyF7vR.js → chunk-55IACEB6-B-p_QNqz.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-C403gCUk.js → chunk-5FUZZQ4R-D6U6tV_j.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-CjVzXQEp.js → chunk-5PVQY5BW-CYK76xfs.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-D5bhMrtY.js → chunk-67CJDMHE-BC9js-lf.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-Si7Lgrwc.js → chunk-7N4EOEYR-4j2OqKkv.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-DMuHtDqO.js → chunk-AA7GKIK3-Coen-fXN.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-L79XKVcb.js → chunk-BSJP7CBP-CAiOBvec.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-C0O7Upmg.js → chunk-CIAEETIT-AJzzpZVb.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-DJcJAsAg.js → chunk-EDXVE4YY-BL4BKozX.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-CFDNvYu1.js → chunk-ENJZ2VHE-mhAFG8UD.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-C_E43NFJ.js → chunk-FMBD7UC4-H231gZA_.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-D9lWWHAu.js → chunk-FOC6F5B3-Cl3ZZjYG.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-ecLOxGhL.js → chunk-ICPOFSXX-DOEzvzJa.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-DuhsNH4c.js → chunk-K5T4RW27-C_ipbUDD.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-B4-A1Abi.js → chunk-KGLVRYIC-CTsDNSCU.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-BxqgHRgT.js → chunk-LIHQZDEY-DvSXhkGf.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-DEYQ5WaJ.js → chunk-ORNJ4GCN-p574NOI7.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-B7MW66KB.js → chunk-OYMX7WX6-BlEgFM6U.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-DpF06ZZQ.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-BMawmsyk.js → chunk-U2HBQHQK-B2bDK0jv.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-CT6g7pno.js → chunk-X2U36JSP-D69BxKFw.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-CBfZXZDB.js → chunk-XPW4576I-Dm-PcyUi.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-xeAluiAH.js → chunk-YZCP3GAM-Be8RnXgx.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-BRN9qUC5.js → chunk-ZZ45TVLE-Ck8PCTa4.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CYbXvKLI.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DEyHzRhq.js +1 -0
- package/payload/server/public/assets/clone-y8gexbBy.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-Br2gjtEO.js → cose-bilkent-S5V4N54A-CmkW2Eaj.js} +1 -1
- package/payload/server/public/assets/{dagre-DTjePoco.js → dagre-Dqp-ns8F.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-DHBkRke4.js → dagre-KV5264BT-ZgWWXPLc.js} +1 -1
- package/payload/server/public/assets/data-gy6QH9c1.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-BIq1-idL.js → diagram-5BDNPKRD-CTX5-ScM.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BsIUDzV6.js → diagram-G4DWMVQ6-BovIsO6H.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-CgHSri2i.js → diagram-MMDJMWI5-DcETsQy-.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-Ce2Wh9ZX.js → diagram-TYMM5635-yyq6peoZ.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-BU0Kh6OQ.js → erDiagram-SMLLAGMA-CiNToftB.js} +1 -1
- package/payload/server/public/assets/{flatten-Bo6YRmWl.js → flatten-BtFI066E.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B0N06MF7.js → flowDiagram-DWJPFMVM-Xnl3SpIM.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BVbx4ARZ.js → ganttDiagram-T4ZO3ILL-C1iyWe0f.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-CNs-LD5i.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C-xRJ94t.js → gitGraphDiagram-UUTBAWPF-D97pbMQb.js} +1 -1
- package/payload/server/public/assets/graph-labels-cZu4pK16.js +1 -0
- package/payload/server/public/assets/{graph-g48ZcA5M.js → graph-qz5tFKqU.js} +3 -3
- package/payload/server/public/assets/{graphlib-YmNcoMjY.js → graphlib-Lq8ijgON.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-DsTNigSS.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-C_OarRTA.js +2 -0
- package/payload/server/public/assets/{isEmpty-D6Kr-M1M.js → isEmpty-D6QovjYR.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DTrq54yC.js → ishikawaDiagram-UXIWVN3A-B8XBdjJn.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-OZZZMrFX.js → journeyDiagram-VCZTEJTY-CZYbiOaQ.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY--w-IP9pN.js → kanban-definition-6JOO6SKY-B1PybFoh.js} +1 -1
- package/payload/server/public/assets/{line-Ckeulv5T.js → line-D-tw3hHp.js} +1 -1
- package/payload/server/public/assets/{linear-DOh_6k2k.js → linear-BHhXD3cd.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-CVRAxYRD.js → mermaid-parser.core-C9RAnysF.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-B-mE18I1.js → mermaid.core-B532LT1r.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-Bm8mDicL.js → mindmap-definition-QFDTVHPH-DGlgeeTV.js} +1 -1
- package/payload/server/public/assets/{ordinal-BDi6f4xk.js → ordinal-Bl-aM5b9.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-DGES22b-.js +1 -0
- package/payload/server/public/assets/pie-ZZUOXDRM-ChKeDbzt.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-BCmRLgGO.js → pieDiagram-DEJITSTG-DV9FIWko.js} +1 -1
- package/payload/server/public/assets/{public-DknO-g9S.js → public-Bu2_Xi0a.js} +5 -5
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CniTIUTm.js → quadrantDiagram-34T5L4WZ-Betwya4l.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-FGG5Fs7N.js +1 -0
- package/payload/server/public/assets/{reduce-CGi9ik8i.js → reduce-BD4xUd2c.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-CoxBSj9M.js → requirementDiagram-MS252O5E-Cq3vODdg.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BjS-4jzq.js → sankeyDiagram-XADWPNL6-x8krXWcS.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-B9jVOnPR.js → sequenceDiagram-FGHM5R23-i-_uH-Yl.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BvOQPzP8.js → stateDiagram-FHFEXIEX-il4KqSgI.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B6zNJ6Tv.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CdfgWLo1.js → timeline-definition-GMOUNBTQ-DATdZkA5.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-VAQQdbtf.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-DKchO3zI.js +1 -0
- package/payload/server/public/assets/useSelectionMode-A5KItZ2T.js +13 -0
- package/payload/server/public/assets/{brand-D0gNihp7.css → useSelectionMode-C-Ojh7W9.css} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-JCgpIbj-.js → vennDiagram-DHZGUBPP-BJh9tJTt.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-CBGtx0bS.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Dei3VqHo.js → wardleyDiagram-NUSXRM2D-EMN1Hdfg.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DUtIyoIb.js → xychartDiagram-5P7HB3ND-DbUWXa7T.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +5 -6
- package/payload/server/public/public.html +4 -5
- package/payload/server/server.js +53 -12
- package/payload/platform/plugins/admin/hooks/__tests__/insight.test.sh +0 -395
- package/payload/platform/plugins/admin/hooks/insight.sh +0 -219
- package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +0 -239
- package/payload/premium-plugins/writer-craft/hooks/__tests__/voice-session-end-text.test.sh +0 -284
- package/payload/premium-plugins/writer-craft/hooks/voice-session-end-text.sh +0 -75
- package/payload/premium-plugins/writer-craft/mcp/src/cli/ingest-session-text.ts +0 -65
- package/payload/server/public/assets/AdminShell-892Jy_rs.js +0 -1
- package/payload/server/public/assets/Checkbox-Bc2QzX9b.js +0 -1
- package/payload/server/public/assets/admin-D3K13ndi.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL--v-pJPNp.js +0 -1
- package/payload/server/public/assets/brand-CcN3dELF.js +0 -9
- package/payload/server/public/assets/channel-B1IT7to2.js +0 -1
- package/payload/server/public/assets/chunk-336JU56O-CdKRCIeE.js +0 -2
- package/payload/server/public/assets/chunk-426QAEUC-BybuQ3Ve.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-Bd-GrQM6.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-rjCize6i.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BORWOUt0.js +0 -1
- package/payload/server/public/assets/clone-Csqv5U6T.js +0 -1
- package/payload/server/public/assets/data-Br-pdljK.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-CI0s_tqn.js +0 -1
- package/payload/server/public/assets/graph-labels-BYH-IPCb.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-g3gYW7Qm.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-Di6oPQ_-.js +0 -2
- package/payload/server/public/assets/packet-4T2RLAQJ-CT0TB9HI.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-CXLe7TFF.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-DnPLBl-D.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-v4ND10uR.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-C3cb7Xwe.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-Dc7G3Bgm.js +0 -1
- package/payload/server/public/assets/useSelectionMode-DwsyptOw.js +0 -5
- package/payload/server/public/assets/wardley-RL74JXVD-DtgibWAt.js +0 -1
- /package/payload/server/public/assets/{_baseFor-Cam2PbSt.js → _baseFor-Cs8Y-rGh.js} +0 -0
- /package/payload/server/public/assets/{array-DYRGGQae.js → array-iHZP4KWJ.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-nWsJMTNI.js → cytoscape.esm-BR2GOQ8_.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-Du1XY3Dp.js → defaultLocale-B9aLeOTg.js} +0 -0
- /package/payload/server/public/assets/{dist-BzAsli7o.js → dist-DB-VPj_8.js} +0 -0
- /package/payload/server/public/assets/{init-B5BXBRcm.js → init-BNFRgqHM.js} +0 -0
- /package/payload/server/public/assets/{katex-HOUACuRw.js → katex-B-EfS3nw.js} +0 -0
- /package/payload/server/public/assets/{path-CNO468J-.js → path-DmWWdwp7.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-DRO6hWPh.js → rough.esm-Ci7Kjt46.js} +0 -0
- /package/payload/server/public/assets/{src-CWiyyVfn.js → src-C1jfwBq0.js} +0 -0
|
@@ -1,127 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* voice-ingest-session-text —
|
|
3
|
-
* session
|
|
4
|
-
*
|
|
2
|
+
* voice-ingest-session-text — write operator turns the agent read from its
|
|
3
|
+
* own session context as :Message {format:'text', source:'admin-pty'} corpus
|
|
4
|
+
* nodes.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* session
|
|
8
|
-
*
|
|
6
|
+
* Invoked on demand by the voice-mirror skill (Task 644): the operator asks to
|
|
7
|
+
* capture this session's voice, the admin agent extracts its own operator
|
|
8
|
+
* turns from the live conversation context, and passes them here as `turns`.
|
|
9
|
+
* Re-running with the same turns is a no-op — MERGE on (contentHash, accountId)
|
|
10
|
+
* is the deduplication primitive.
|
|
9
11
|
*
|
|
10
12
|
* After ingest, triggers voice-distil-profile {format:'text'} so the cadence
|
|
11
13
|
* guard decides whether distillation runs.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* "Real operator text" extraction rules (excludes):
|
|
17
|
-
* - type != "user" or message.role != "user" → not the operator
|
|
18
|
-
* - content is tool_result-only → tool reply, not turn
|
|
15
|
+
* "Real operator text" filter (each supplied turn is excluded when):
|
|
16
|
+
* - text is empty after trimming → nothing to ingest
|
|
19
17
|
* - text starts with "/" → slash command
|
|
20
18
|
* - text contains "<system-reminder>" → harness injection
|
|
21
19
|
* - text.length >= 4096 → likely pasted content
|
|
22
|
-
* - text is empty after trimming → nothing to ingest
|
|
23
20
|
*/
|
|
24
21
|
import { createHash } from "node:crypto";
|
|
25
|
-
import { createReadStream } from "node:fs";
|
|
26
|
-
import { createInterface } from "node:readline";
|
|
27
22
|
import { getSession } from "../lib/neo4j.js";
|
|
28
23
|
import { voiceDistilProfile } from "./voice-distil-profile.js";
|
|
29
24
|
/**
|
|
30
|
-
*
|
|
31
|
-
* Returns null when the
|
|
25
|
+
* Applies the "real operator text" exclusions to a single supplied turn.
|
|
26
|
+
* Returns the trimmed text to ingest, or null when the turn should be skipped.
|
|
27
|
+
* Exported for testability (no DB required).
|
|
32
28
|
*/
|
|
33
|
-
export function
|
|
34
|
-
if (
|
|
35
|
-
return null;
|
|
36
|
-
const rec = record;
|
|
37
|
-
if (rec["type"] !== "user")
|
|
38
|
-
return null;
|
|
39
|
-
const msg = rec["message"];
|
|
40
|
-
if (!msg || typeof msg !== "object")
|
|
41
|
-
return null;
|
|
42
|
-
const message = msg;
|
|
43
|
-
if (message["role"] !== "user")
|
|
44
|
-
return null;
|
|
45
|
-
const content = message["content"];
|
|
46
|
-
let text = "";
|
|
47
|
-
if (typeof content === "string") {
|
|
48
|
-
text = content;
|
|
49
|
-
}
|
|
50
|
-
else if (Array.isArray(content)) {
|
|
51
|
-
// Must have at least one non-tool_result block to be a real turn.
|
|
52
|
-
const nonToolResult = content.filter((b) => typeof b === "object" && b !== null && b["type"] !== "tool_result");
|
|
53
|
-
if (nonToolResult.length === 0)
|
|
54
|
-
return null;
|
|
55
|
-
// Collect text from all text-type content blocks.
|
|
56
|
-
const parts = [];
|
|
57
|
-
for (const block of content) {
|
|
58
|
-
if (typeof block !== "object" || block === null)
|
|
59
|
-
continue;
|
|
60
|
-
const b = block;
|
|
61
|
-
if (b["type"] === "text" && typeof b["text"] === "string") {
|
|
62
|
-
parts.push(b["text"]);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
text = parts.join("");
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
29
|
+
export function filterOperatorText(text) {
|
|
30
|
+
if (typeof text !== "string")
|
|
68
31
|
return null;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (text.length === 0)
|
|
32
|
+
const trimmed = text.trim();
|
|
33
|
+
if (trimmed.length === 0)
|
|
72
34
|
return null;
|
|
73
|
-
|
|
74
|
-
if (text.startsWith("/"))
|
|
35
|
+
if (trimmed.startsWith("/"))
|
|
75
36
|
return null; // slash command
|
|
76
|
-
if (
|
|
37
|
+
if (trimmed.includes("<system-reminder>"))
|
|
77
38
|
return null; // harness injection
|
|
78
|
-
if (
|
|
39
|
+
if (trimmed.length >= 4096)
|
|
79
40
|
return null; // paste block
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Parse a session JSONL file and return all real operator turn texts.
|
|
84
|
-
* Exported for testability (no DB required).
|
|
85
|
-
*/
|
|
86
|
-
export async function extractOperatorTurns(jsonlPath) {
|
|
87
|
-
const turns = [];
|
|
88
|
-
const rl = createInterface({
|
|
89
|
-
input: createReadStream(jsonlPath, { encoding: "utf-8" }),
|
|
90
|
-
crlfDelay: Infinity,
|
|
91
|
-
});
|
|
92
|
-
for await (const line of rl) {
|
|
93
|
-
const trimmed = line.trim();
|
|
94
|
-
if (!trimmed)
|
|
95
|
-
continue;
|
|
96
|
-
let record;
|
|
97
|
-
try {
|
|
98
|
-
record = JSON.parse(trimmed);
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
const text = extractOperatorText(record);
|
|
104
|
-
if (text !== null) {
|
|
105
|
-
turns.push(text);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return turns;
|
|
41
|
+
return trimmed;
|
|
109
42
|
}
|
|
110
43
|
export async function voiceIngestSessionText(params) {
|
|
111
|
-
const {
|
|
44
|
+
const { turns, accountId, userId, sessionId = null } = params;
|
|
112
45
|
if (!accountId || !userId) {
|
|
113
46
|
throw new Error("voice-ingest-session-text: accountId and userId required");
|
|
114
47
|
}
|
|
115
|
-
if (!
|
|
116
|
-
throw new Error("voice-ingest-session-text:
|
|
117
|
-
}
|
|
118
|
-
// 1. Extract operator turns from the JSONL.
|
|
119
|
-
let allTurns;
|
|
120
|
-
try {
|
|
121
|
-
allTurns = await extractOperatorTurns(sessionJsonlPath);
|
|
48
|
+
if (!Array.isArray(turns)) {
|
|
49
|
+
throw new Error("voice-ingest-session-text: turns array required");
|
|
122
50
|
}
|
|
123
|
-
|
|
124
|
-
|
|
51
|
+
// 1. Apply the operator-text filter to each supplied turn.
|
|
52
|
+
const allTurns = [];
|
|
53
|
+
for (const turn of turns) {
|
|
54
|
+
const text = filterOperatorText(turn);
|
|
55
|
+
if (text !== null)
|
|
56
|
+
allTurns.push(text);
|
|
125
57
|
}
|
|
126
58
|
if (allTurns.length === 0) {
|
|
127
59
|
process.stderr.write(`[voice-ingest-session-text] sessionId=${sessionId ?? "unknown"} adminUser=${userId} turns=0 bytes=0\n`);
|
package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voice-ingest-session-text.js","sourceRoot":"","sources":["../../src/tools/voice-ingest-session-text.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"voice-ingest-session-text.js","sourceRoot":"","sources":["../../src/tools/voice-ingest-session-text.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,14 +16,13 @@
|
|
|
16
16
|
* collapsing a failed lookup into the no-data payload.
|
|
17
17
|
* 9. voice-tag-content validates mode and format enums, requires format,
|
|
18
18
|
* and returns zero counts on empty nodeIds (with format supplied).
|
|
19
|
-
* 11. voice-ingest-session-text:
|
|
19
|
+
* 11. voice-ingest-session-text: filterOperatorText() keeps real turns
|
|
20
20
|
* and excludes slash commands, paste blocks, and system reminders.
|
|
21
21
|
*
|
|
22
22
|
* Exit code: 0 on pass, 1 on any assertion failure.
|
|
23
23
|
*/
|
|
24
24
|
import { strict as assert } from "node:assert";
|
|
25
|
-
import { readFileSync
|
|
26
|
-
import { tmpdir } from "node:os";
|
|
25
|
+
import { readFileSync } from "node:fs";
|
|
27
26
|
import { join, dirname } from "node:path";
|
|
28
27
|
import { fileURLToPath } from "node:url";
|
|
29
28
|
import { readdirSync } from "node:fs";
|
|
@@ -132,8 +131,7 @@ await check("voice-record-feedback exports voiceRecordFeedback function", () =>
|
|
|
132
131
|
});
|
|
133
132
|
await check("voice-ingest-session-text exports required functions", () => {
|
|
134
133
|
assert.equal(typeof ingestMod.voiceIngestSessionText, "function");
|
|
135
|
-
assert.equal(typeof ingestMod.
|
|
136
|
-
assert.equal(typeof ingestMod.extractOperatorText, "function");
|
|
134
|
+
assert.equal(typeof ingestMod.filterOperatorText, "function");
|
|
137
135
|
});
|
|
138
136
|
|
|
139
137
|
// ---------------------------------------------------------------------------
|
|
@@ -294,127 +292,52 @@ await check("voice-tag-content returns zero counts on empty nodeIds (no DB hit)"
|
|
|
294
292
|
});
|
|
295
293
|
|
|
296
294
|
// ---------------------------------------------------------------------------
|
|
297
|
-
// 7. voice-ingest-session-text:
|
|
295
|
+
// 7. voice-ingest-session-text: operator-turn filter (no DB required).
|
|
298
296
|
// ---------------------------------------------------------------------------
|
|
299
|
-
console.log("\n--
|
|
297
|
+
console.log("\n-- operator-turn filter --");
|
|
300
298
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
await check("extractOperatorText: real user turn is extracted", () => {
|
|
306
|
-
const record = { type: "user", message: { role: "user", content: "Hello world" } };
|
|
307
|
-
const result = ingestMod.extractOperatorText(record);
|
|
308
|
-
assert.equal(result, "Hello world");
|
|
309
|
-
});
|
|
310
|
-
await check("extractOperatorText: slash command is excluded", () => {
|
|
311
|
-
const record = { type: "user", message: { role: "user", content: "/end" } };
|
|
312
|
-
assert.equal(ingestMod.extractOperatorText(record), null);
|
|
299
|
+
await check("filterOperatorText: real turn is kept (and trimmed)", () => {
|
|
300
|
+
assert.equal(ingestMod.filterOperatorText(" Hello world "), "Hello world");
|
|
313
301
|
});
|
|
314
|
-
await check("
|
|
315
|
-
|
|
316
|
-
type: "user",
|
|
317
|
-
message: { role: "user", content: "<system-reminder>some injected text</system-reminder>" },
|
|
318
|
-
};
|
|
319
|
-
assert.equal(ingestMod.extractOperatorText(record), null);
|
|
302
|
+
await check("filterOperatorText: slash command is excluded", () => {
|
|
303
|
+
assert.equal(ingestMod.filterOperatorText("/end"), null);
|
|
320
304
|
});
|
|
321
|
-
await check("
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
assert.equal(ingestMod.extractOperatorText(record), null);
|
|
305
|
+
await check("filterOperatorText: system-reminder is excluded", () => {
|
|
306
|
+
assert.equal(
|
|
307
|
+
ingestMod.filterOperatorText("<system-reminder>some injected text</system-reminder>"),
|
|
308
|
+
null,
|
|
309
|
+
);
|
|
327
310
|
});
|
|
328
|
-
await check("
|
|
329
|
-
|
|
330
|
-
type: "user",
|
|
331
|
-
message: { role: "user", content: "x".repeat(4096) },
|
|
332
|
-
};
|
|
333
|
-
assert.equal(ingestMod.extractOperatorText(record), null);
|
|
311
|
+
await check("filterOperatorText: empty / whitespace-only is excluded", () => {
|
|
312
|
+
assert.equal(ingestMod.filterOperatorText(" "), null);
|
|
334
313
|
});
|
|
335
|
-
await check("
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
assert.equal(ingestMod.extractOperatorText(record), body);
|
|
314
|
+
await check("filterOperatorText: non-string is excluded", () => {
|
|
315
|
+
assert.equal(ingestMod.filterOperatorText(undefined), null);
|
|
316
|
+
assert.equal(ingestMod.filterOperatorText(42), null);
|
|
339
317
|
});
|
|
340
|
-
await check("
|
|
341
|
-
|
|
342
|
-
assert.equal(ingestMod.
|
|
318
|
+
await check("filterOperatorText: paste block >= 4096 chars is excluded", () => {
|
|
319
|
+
assert.equal(ingestMod.filterOperatorText("x".repeat(4096)), null);
|
|
320
|
+
assert.equal(ingestMod.filterOperatorText("x".repeat(4097)), null);
|
|
343
321
|
});
|
|
344
|
-
await check("
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
message: {
|
|
348
|
-
role: "user",
|
|
349
|
-
content: [{ type: "tool_result", tool_use_id: "x", content: "ok" }],
|
|
350
|
-
},
|
|
351
|
-
};
|
|
352
|
-
assert.equal(ingestMod.extractOperatorText(record), null);
|
|
353
|
-
});
|
|
354
|
-
await check("extractOperatorText: content array with text block is extracted", () => {
|
|
355
|
-
const record = {
|
|
356
|
-
type: "user",
|
|
357
|
-
message: {
|
|
358
|
-
role: "user",
|
|
359
|
-
content: [{ type: "text", text: "Hello from array" }],
|
|
360
|
-
},
|
|
361
|
-
};
|
|
362
|
-
assert.equal(ingestMod.extractOperatorText(record), "Hello from array");
|
|
322
|
+
await check("filterOperatorText: 4095 chars is included", () => {
|
|
323
|
+
const body = "x".repeat(4095);
|
|
324
|
+
assert.equal(ingestMod.filterOperatorText(body), body);
|
|
363
325
|
});
|
|
364
326
|
|
|
365
|
-
//
|
|
366
|
-
// Expected: extractOperatorTurns returns 3 strings.
|
|
327
|
+
// turns-array semantics: a mixed array filters down to the real turns.
|
|
367
328
|
await check(
|
|
368
|
-
"
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
//
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
// 2 assistant turns
|
|
378
|
-
makeJsonlLine("assistant", "assistant", "Agent reply 1"),
|
|
379
|
-
makeJsonlLine("assistant", "assistant", "Agent reply 2"),
|
|
380
|
-
// 1 slash command
|
|
381
|
-
makeJsonlLine("user", "user", "/end"),
|
|
382
|
-
// 1 system reminder
|
|
383
|
-
makeJsonlLine("user", "user", "<system-reminder>injected</system-reminder>"),
|
|
329
|
+
"turns array: 3 real turns + 3 excluded → filterOperatorText keeps 3",
|
|
330
|
+
() => {
|
|
331
|
+
const turns = [
|
|
332
|
+
"First real turn",
|
|
333
|
+
"Second real turn",
|
|
334
|
+
"/end", // slash command
|
|
335
|
+
"<system-reminder>injected</system-reminder>", // harness injection
|
|
336
|
+
"Third real turn",
|
|
337
|
+
" ", // whitespace only
|
|
384
338
|
];
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
const turns = await ingestMod.extractOperatorTurns(jsonlPath);
|
|
388
|
-
assert.equal(turns.length, 3, `expected 3 turns, got ${turns.length}`);
|
|
389
|
-
assert.equal(turns[0], "First real turn");
|
|
390
|
-
assert.equal(turns[1], "Second real turn");
|
|
391
|
-
assert.equal(turns[2], "Third real turn");
|
|
392
|
-
} finally {
|
|
393
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
394
|
-
}
|
|
395
|
-
},
|
|
396
|
-
);
|
|
397
|
-
|
|
398
|
-
// Second-run fixture: same lines written to same path → same 3 turns extracted.
|
|
399
|
-
// (Actual dedup happens in the DB via contentHash MERGE; extraction is idempotent.)
|
|
400
|
-
await check(
|
|
401
|
-
"extractOperatorTurns: re-running same JSONL extracts same turns (dedup is in DB)",
|
|
402
|
-
async () => {
|
|
403
|
-
const tmp = mkdtempSync(join(tmpdir(), "smoke-ingest-dedup-"));
|
|
404
|
-
const jsonlPath = join(tmp, "session.jsonl");
|
|
405
|
-
const lines = [
|
|
406
|
-
makeJsonlLine("user", "user", "Dedupe turn"),
|
|
407
|
-
makeJsonlLine("user", "user", "/skip-cmd"),
|
|
408
|
-
];
|
|
409
|
-
writeFileSync(jsonlPath, lines.join("\n") + "\n");
|
|
410
|
-
try {
|
|
411
|
-
const turns1 = await ingestMod.extractOperatorTurns(jsonlPath);
|
|
412
|
-
const turns2 = await ingestMod.extractOperatorTurns(jsonlPath);
|
|
413
|
-
assert.deepEqual(turns1, turns2, "idempotent: same JSONL gives same turns");
|
|
414
|
-
assert.equal(turns1.length, 1);
|
|
415
|
-
} finally {
|
|
416
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
417
|
-
}
|
|
339
|
+
const kept = turns.map((t) => ingestMod.filterOperatorText(t)).filter((t) => t !== null);
|
|
340
|
+
assert.deepEqual(kept, ["First real turn", "Second real turn", "Third real turn"]);
|
|
418
341
|
},
|
|
419
342
|
);
|
|
420
343
|
|
|
@@ -348,13 +348,13 @@ server.tool(
|
|
|
348
348
|
|
|
349
349
|
server.tool(
|
|
350
350
|
"voice-ingest-session-text",
|
|
351
|
-
"
|
|
351
|
+
"Write operator turns from the current session as :Message {format:'text', source:'admin-pty', authorshipMode:'human-only'} corpus nodes. The admin agent reads its own operator turns from the live conversation context and passes them as `turns`. Deduplication via SHA256 contentHash — re-running with the same turns is a no-op. Triggers voice-distil-profile {format:'text'} after ingest (cadence guard decides whether distillation runs). Invoked on demand by the voice-mirror skill when the operator asks to capture this session's voice.",
|
|
352
352
|
{
|
|
353
|
-
|
|
354
|
-
sessionId: z.string().optional().describe("Session ID for provenance
|
|
353
|
+
turns: z.array(z.string()).describe("Operator turns the agent read from its own session context (one string per operator message). Slash commands, harness injections, and large paste blocks are filtered out by the tool."),
|
|
354
|
+
sessionId: z.string().optional().describe("Session ID for provenance."),
|
|
355
355
|
userId: z.string().optional().describe("Operator AdminUser identifier. Defaults to ADMIN_USER_ID env."),
|
|
356
356
|
},
|
|
357
|
-
async ({
|
|
357
|
+
async ({ turns, sessionId, userId }) => {
|
|
358
358
|
if (!accountId) return refuseNoAccount("voice-ingest-session-text");
|
|
359
359
|
const resolvedUserId = userId ?? resolveUserId();
|
|
360
360
|
if (!resolvedUserId) {
|
|
@@ -370,7 +370,7 @@ server.tool(
|
|
|
370
370
|
}
|
|
371
371
|
try {
|
|
372
372
|
const result = await voiceIngestSessionText({
|
|
373
|
-
|
|
373
|
+
turns,
|
|
374
374
|
accountId,
|
|
375
375
|
userId: resolvedUserId,
|
|
376
376
|
sessionId,
|
|
@@ -19,7 +19,7 @@ export function notTrashed(alias: string): string {
|
|
|
19
19
|
*
|
|
20
20
|
* Imported by `voice-distil-profile` (count + sample walks),
|
|
21
21
|
* `voice-retrieve-conditioning` (exemplar walk), `voice-tag-content` (tag
|
|
22
|
-
* writes), and `voice-ingest-session-text` (
|
|
22
|
+
* writes), and `voice-ingest-session-text` (on-demand session-text ingest). The single
|
|
23
23
|
* load-bearing filter — when the corpus rules change, this is the only place
|
|
24
24
|
* to edit.
|
|
25
25
|
*
|
|
@@ -1,34 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* voice-ingest-session-text —
|
|
3
|
-
* session
|
|
4
|
-
*
|
|
2
|
+
* voice-ingest-session-text — write operator turns the agent read from its
|
|
3
|
+
* own session context as :Message {format:'text', source:'admin-pty'} corpus
|
|
4
|
+
* nodes.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* session
|
|
8
|
-
*
|
|
6
|
+
* Invoked on demand by the voice-mirror skill (Task 644): the operator asks to
|
|
7
|
+
* capture this session's voice, the admin agent extracts its own operator
|
|
8
|
+
* turns from the live conversation context, and passes them here as `turns`.
|
|
9
|
+
* Re-running with the same turns is a no-op — MERGE on (contentHash, accountId)
|
|
10
|
+
* is the deduplication primitive.
|
|
9
11
|
*
|
|
10
12
|
* After ingest, triggers voice-distil-profile {format:'text'} so the cadence
|
|
11
13
|
* guard decides whether distillation runs.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* "Real operator text" extraction rules (excludes):
|
|
17
|
-
* - type != "user" or message.role != "user" → not the operator
|
|
18
|
-
* - content is tool_result-only → tool reply, not turn
|
|
15
|
+
* "Real operator text" filter (each supplied turn is excluded when):
|
|
16
|
+
* - text is empty after trimming → nothing to ingest
|
|
19
17
|
* - text starts with "/" → slash command
|
|
20
18
|
* - text contains "<system-reminder>" → harness injection
|
|
21
19
|
* - text.length >= 4096 → likely pasted content
|
|
22
|
-
* - text is empty after trimming → nothing to ingest
|
|
23
20
|
*/
|
|
24
21
|
import { createHash } from "node:crypto";
|
|
25
|
-
import { createReadStream } from "node:fs";
|
|
26
|
-
import { createInterface } from "node:readline";
|
|
27
22
|
import { getSession } from "../lib/neo4j.js";
|
|
28
23
|
import { voiceDistilProfile } from "./voice-distil-profile.js";
|
|
29
24
|
|
|
30
25
|
export interface VoiceIngestSessionTextParams {
|
|
31
|
-
|
|
26
|
+
turns: string[];
|
|
32
27
|
accountId: string;
|
|
33
28
|
userId: string;
|
|
34
29
|
sessionId?: string;
|
|
@@ -41,109 +36,37 @@ export interface VoiceIngestSessionTextResult {
|
|
|
41
36
|
}
|
|
42
37
|
|
|
43
38
|
/**
|
|
44
|
-
*
|
|
45
|
-
* Returns null when the
|
|
46
|
-
*/
|
|
47
|
-
export function extractOperatorText(record: unknown): string | null {
|
|
48
|
-
if (!record || typeof record !== "object") return null;
|
|
49
|
-
const rec = record as Record<string, unknown>;
|
|
50
|
-
|
|
51
|
-
if (rec["type"] !== "user") return null;
|
|
52
|
-
|
|
53
|
-
const msg = rec["message"];
|
|
54
|
-
if (!msg || typeof msg !== "object") return null;
|
|
55
|
-
const message = msg as Record<string, unknown>;
|
|
56
|
-
if (message["role"] !== "user") return null;
|
|
57
|
-
|
|
58
|
-
const content = message["content"];
|
|
59
|
-
let text = "";
|
|
60
|
-
|
|
61
|
-
if (typeof content === "string") {
|
|
62
|
-
text = content;
|
|
63
|
-
} else if (Array.isArray(content)) {
|
|
64
|
-
// Must have at least one non-tool_result block to be a real turn.
|
|
65
|
-
const nonToolResult = content.filter(
|
|
66
|
-
(b) => typeof b === "object" && b !== null && (b as Record<string, unknown>)["type"] !== "tool_result",
|
|
67
|
-
);
|
|
68
|
-
if (nonToolResult.length === 0) return null;
|
|
69
|
-
|
|
70
|
-
// Collect text from all text-type content blocks.
|
|
71
|
-
const parts: string[] = [];
|
|
72
|
-
for (const block of content) {
|
|
73
|
-
if (typeof block !== "object" || block === null) continue;
|
|
74
|
-
const b = block as Record<string, unknown>;
|
|
75
|
-
if (b["type"] === "text" && typeof b["text"] === "string") {
|
|
76
|
-
parts.push(b["text"]);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
text = parts.join("");
|
|
80
|
-
} else {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
text = text.trim();
|
|
85
|
-
if (text.length === 0) return null;
|
|
86
|
-
|
|
87
|
-
// Exclusions.
|
|
88
|
-
if (text.startsWith("/")) return null; // slash command
|
|
89
|
-
if (text.includes("<system-reminder>")) return null; // harness injection
|
|
90
|
-
if (text.length >= 4096) return null; // paste block
|
|
91
|
-
|
|
92
|
-
return text;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Parse a session JSONL file and return all real operator turn texts.
|
|
39
|
+
* Applies the "real operator text" exclusions to a single supplied turn.
|
|
40
|
+
* Returns the trimmed text to ingest, or null when the turn should be skipped.
|
|
97
41
|
* Exported for testability (no DB required).
|
|
98
42
|
*/
|
|
99
|
-
export
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
for await (const line of rl) {
|
|
108
|
-
const trimmed = line.trim();
|
|
109
|
-
if (!trimmed) continue;
|
|
110
|
-
let record: unknown;
|
|
111
|
-
try {
|
|
112
|
-
record = JSON.parse(trimmed);
|
|
113
|
-
} catch {
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
const text = extractOperatorText(record);
|
|
117
|
-
if (text !== null) {
|
|
118
|
-
turns.push(text);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return turns;
|
|
43
|
+
export function filterOperatorText(text: unknown): string | null {
|
|
44
|
+
if (typeof text !== "string") return null;
|
|
45
|
+
const trimmed = text.trim();
|
|
46
|
+
if (trimmed.length === 0) return null;
|
|
47
|
+
if (trimmed.startsWith("/")) return null; // slash command
|
|
48
|
+
if (trimmed.includes("<system-reminder>")) return null; // harness injection
|
|
49
|
+
if (trimmed.length >= 4096) return null; // paste block
|
|
50
|
+
return trimmed;
|
|
123
51
|
}
|
|
124
52
|
|
|
125
53
|
export async function voiceIngestSessionText(
|
|
126
54
|
params: VoiceIngestSessionTextParams,
|
|
127
55
|
): Promise<VoiceIngestSessionTextResult> {
|
|
128
|
-
const {
|
|
56
|
+
const { turns, accountId, userId, sessionId = null } = params;
|
|
129
57
|
|
|
130
58
|
if (!accountId || !userId) {
|
|
131
59
|
throw new Error("voice-ingest-session-text: accountId and userId required");
|
|
132
60
|
}
|
|
133
|
-
if (!
|
|
134
|
-
throw new Error("voice-ingest-session-text:
|
|
61
|
+
if (!Array.isArray(turns)) {
|
|
62
|
+
throw new Error("voice-ingest-session-text: turns array required");
|
|
135
63
|
}
|
|
136
64
|
|
|
137
|
-
// 1.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
throw new Error(
|
|
143
|
-
`voice-ingest-session-text: failed to read JSONL at '${sessionJsonlPath}': ${
|
|
144
|
-
err instanceof Error ? err.message : String(err)
|
|
145
|
-
}`,
|
|
146
|
-
);
|
|
65
|
+
// 1. Apply the operator-text filter to each supplied turn.
|
|
66
|
+
const allTurns: string[] = [];
|
|
67
|
+
for (const turn of turns) {
|
|
68
|
+
const text = filterOperatorText(turn);
|
|
69
|
+
if (text !== null) allTurns.push(text);
|
|
147
70
|
}
|
|
148
71
|
|
|
149
72
|
if (allTurns.length === 0) {
|