@rubytech/create-maxy-code 0.1.255 → 0.1.257

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/__tests__/plugin-install.test.js +58 -40
  2. package/dist/index.js +77 -26
  3. package/dist/lib/plugin-install.js +31 -29
  4. package/package.json +1 -1
  5. package/payload/platform/config/brand-registry.json +8 -0
  6. package/payload/platform/config/brand.json +3 -3
  7. package/payload/platform/lib/graph-search/src/__tests__/fulltext-coverage.test.ts +12 -0
  8. package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
  9. package/payload/platform/lib/graph-write/dist/index.js +2 -0
  10. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  11. package/payload/platform/lib/graph-write/src/index.ts +2 -0
  12. package/payload/platform/neo4j/schema.cypher +126 -0
  13. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  14. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  15. package/payload/platform/plugins/admin/PLUGIN.md +3 -6
  16. package/payload/platform/plugins/admin/mcp/dist/index.js +0 -60
  17. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  18. package/payload/platform/plugins/admin/skills/insight/SKILL.md +24 -0
  19. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +63 -10
  20. package/payload/platform/plugins/business-assistant/PLUGIN.md +1 -1
  21. package/payload/platform/plugins/business-assistant/references/document-management.md +1 -1
  22. package/payload/platform/plugins/business-assistant/references/invoicing.md +2 -2
  23. package/payload/platform/plugins/business-assistant/references/quoting.md +1 -1
  24. package/payload/platform/plugins/docs/PLUGIN.md +1 -0
  25. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  26. package/payload/platform/plugins/docs/references/deployment.md +18 -5
  27. package/payload/platform/plugins/docs/references/memory-guide.md +4 -0
  28. package/payload/platform/plugins/docs/references/platform.md +1 -1
  29. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  30. package/payload/platform/plugins/docs/references/slides.md +31 -0
  31. package/payload/platform/plugins/docs/references/voice-mirror-guide.md +1 -1
  32. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  33. package/payload/platform/plugins/memory/mcp/dist/index.js +1 -1
  34. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  35. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +1 -1
  36. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +1 -1
  37. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +10 -0
  39. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  40. package/payload/platform/plugins/memory/references/schema-construction.md +72 -0
  41. package/payload/platform/plugins/slides/.claude-plugin/plugin.json +8 -0
  42. package/payload/platform/plugins/slides/LICENSE +21 -0
  43. package/payload/platform/plugins/slides/PLUGIN.md +18 -0
  44. package/payload/platform/plugins/slides/PROVENANCE.md +40 -0
  45. package/payload/platform/plugins/slides/commands/add-slide.md +29 -0
  46. package/payload/platform/plugins/slides/commands/slides-claus.md +39 -0
  47. package/payload/platform/plugins/slides/commands/slides-new-component.md +39 -0
  48. package/payload/platform/plugins/slides/commands/slides-outline.md +43 -0
  49. package/payload/platform/plugins/slides/commands/slides-review.md +52 -0
  50. package/payload/platform/plugins/slides/commands/slides-theme.md +64 -0
  51. package/payload/platform/plugins/slides/commands/slides.md +59 -0
  52. package/payload/platform/plugins/slides/skills/deck-system/REFERENCE.md +581 -0
  53. package/payload/platform/plugins/slides/skills/deck-system/SKILL.md +607 -0
  54. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-board.md +426 -0
  55. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-claus.md +185 -0
  56. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-mbb.md +450 -0
  57. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-product-launch.md +579 -0
  58. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sales.md +464 -0
  59. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sequoia.md +489 -0
  60. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING.md +273 -0
  61. package/payload/platform/plugins/slides/skills/deck-system/deck-craft.html +1371 -0
  62. package/payload/platform/plugins/slides/skills/deck-system/deck-solid.html +1667 -0
  63. package/payload/platform/plugins/slides/skills/deck-system/deck.html +1359 -0
  64. package/payload/platform/plugins/url-get/.claude-plugin/plugin.json +1 -1
  65. package/payload/platform/plugins/url-get/PLUGIN.md +26 -21
  66. package/payload/platform/plugins/url-get/mcp/dist/index.js +3 -3
  67. package/payload/platform/plugins/url-get/mcp/dist/index.js.map +1 -1
  68. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts +1 -2
  69. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts.map +1 -1
  70. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js +20 -40
  71. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js.map +1 -1
  72. package/payload/platform/scripts/setup-account.sh +1 -10
  73. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  74. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +0 -1
  75. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  76. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +5 -0
  77. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  78. package/payload/platform/services/claude-session-manager/dist/http-server.js +32 -2
  79. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  80. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +2 -2
  81. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  82. package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
  83. package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +1 -1
  84. package/payload/premium-plugins/writer-craft/PLUGIN.md +2 -2
  85. package/payload/premium-plugins/writer-craft/mcp/dist/index.js +5 -5
  86. package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -1
  87. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts +1 -1
  88. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js +1 -1
  89. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts +4 -8
  90. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts.map +1 -1
  91. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js +30 -98
  92. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js.map +1 -1
  93. package/payload/premium-plugins/writer-craft/mcp/scripts/smoke.mjs +37 -114
  94. package/payload/premium-plugins/writer-craft/mcp/src/index.ts +5 -5
  95. package/payload/premium-plugins/writer-craft/mcp/src/lib/voice-corpus.ts +1 -1
  96. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-ingest-session-text.ts +29 -106
  97. package/payload/premium-plugins/writer-craft/skills/voice-mirror/SKILL.md +15 -17
  98. package/payload/server/public/assets/AdminShell-T-YknnBn.js +1 -0
  99. package/payload/server/public/assets/Checkbox-DmDxpqVv.js +1 -0
  100. package/payload/server/public/assets/admin-COUV-jgt.js +1 -0
  101. package/payload/server/public/assets/{arc-aUiRP9AS.js → arc-B2CweJq3.js} +1 -1
  102. package/payload/server/public/assets/architecture-YZFGNWBL-Dnn6Hc65.js +1 -0
  103. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-c09loTER.js → architectureDiagram-Q4EWVU46-DP2o-MFV.js} +1 -1
  104. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Cjdeyoq1.js → blockDiagram-DXYQGD6D-DO4mcYDJ.js} +1 -1
  105. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-NY6Wlzo2.js → c4Diagram-AHTNJAMY-Sy1giHbj.js} +1 -1
  106. package/payload/server/public/assets/channel-CEpR_0rE.js +1 -0
  107. package/payload/server/public/assets/{chunk-2KRD3SAO-BK3470lx.js → chunk-2KRD3SAO-CKsCYCsN.js} +1 -1
  108. package/payload/server/public/assets/chunk-336JU56O-C0-P-aUF.js +2 -0
  109. package/payload/server/public/assets/chunk-426QAEUC-DFjEt3Zb.js +1 -0
  110. package/payload/server/public/assets/{chunk-4BX2VUAB-BOvVdJLf.js → chunk-4BX2VUAB-B8bqAmBa.js} +1 -1
  111. package/payload/server/public/assets/{chunk-4TB4RGXK-BXpto3yW.js → chunk-4TB4RGXK-D1k0VSlW.js} +1 -1
  112. package/payload/server/public/assets/{chunk-55IACEB6-BwZyF7vR.js → chunk-55IACEB6-B-p_QNqz.js} +1 -1
  113. package/payload/server/public/assets/{chunk-5FUZZQ4R-C403gCUk.js → chunk-5FUZZQ4R-D6U6tV_j.js} +1 -1
  114. package/payload/server/public/assets/{chunk-5PVQY5BW-CjVzXQEp.js → chunk-5PVQY5BW-CYK76xfs.js} +1 -1
  115. package/payload/server/public/assets/{chunk-67CJDMHE-D5bhMrtY.js → chunk-67CJDMHE-BC9js-lf.js} +1 -1
  116. package/payload/server/public/assets/{chunk-7N4EOEYR-Si7Lgrwc.js → chunk-7N4EOEYR-4j2OqKkv.js} +1 -1
  117. package/payload/server/public/assets/{chunk-AA7GKIK3-DMuHtDqO.js → chunk-AA7GKIK3-Coen-fXN.js} +1 -1
  118. package/payload/server/public/assets/{chunk-BSJP7CBP-L79XKVcb.js → chunk-BSJP7CBP-CAiOBvec.js} +1 -1
  119. package/payload/server/public/assets/{chunk-CIAEETIT-C0O7Upmg.js → chunk-CIAEETIT-AJzzpZVb.js} +1 -1
  120. package/payload/server/public/assets/{chunk-EDXVE4YY-DJcJAsAg.js → chunk-EDXVE4YY-BL4BKozX.js} +1 -1
  121. package/payload/server/public/assets/{chunk-ENJZ2VHE-CFDNvYu1.js → chunk-ENJZ2VHE-mhAFG8UD.js} +1 -1
  122. package/payload/server/public/assets/{chunk-FMBD7UC4-C_E43NFJ.js → chunk-FMBD7UC4-H231gZA_.js} +1 -1
  123. package/payload/server/public/assets/{chunk-FOC6F5B3-D9lWWHAu.js → chunk-FOC6F5B3-Cl3ZZjYG.js} +1 -1
  124. package/payload/server/public/assets/{chunk-ICPOFSXX-ecLOxGhL.js → chunk-ICPOFSXX-DOEzvzJa.js} +2 -2
  125. package/payload/server/public/assets/{chunk-K5T4RW27-DuhsNH4c.js → chunk-K5T4RW27-C_ipbUDD.js} +1 -1
  126. package/payload/server/public/assets/{chunk-KGLVRYIC-B4-A1Abi.js → chunk-KGLVRYIC-CTsDNSCU.js} +1 -1
  127. package/payload/server/public/assets/{chunk-LIHQZDEY-BxqgHRgT.js → chunk-LIHQZDEY-DvSXhkGf.js} +1 -1
  128. package/payload/server/public/assets/{chunk-ORNJ4GCN-DEYQ5WaJ.js → chunk-ORNJ4GCN-p574NOI7.js} +1 -1
  129. package/payload/server/public/assets/{chunk-OYMX7WX6-B7MW66KB.js → chunk-OYMX7WX6-BlEgFM6U.js} +1 -1
  130. package/payload/server/public/assets/chunk-QZHKN3VN-DpF06ZZQ.js +1 -0
  131. package/payload/server/public/assets/{chunk-U2HBQHQK-BMawmsyk.js → chunk-U2HBQHQK-B2bDK0jv.js} +1 -1
  132. package/payload/server/public/assets/{chunk-X2U36JSP-CT6g7pno.js → chunk-X2U36JSP-D69BxKFw.js} +1 -1
  133. package/payload/server/public/assets/{chunk-XPW4576I-CBfZXZDB.js → chunk-XPW4576I-Dm-PcyUi.js} +1 -1
  134. package/payload/server/public/assets/{chunk-YZCP3GAM-xeAluiAH.js → chunk-YZCP3GAM-Be8RnXgx.js} +1 -1
  135. package/payload/server/public/assets/{chunk-ZZ45TVLE-BRN9qUC5.js → chunk-ZZ45TVLE-Ck8PCTa4.js} +1 -1
  136. package/payload/server/public/assets/classDiagram-6PBFFD2Q-CYbXvKLI.js +1 -0
  137. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DEyHzRhq.js +1 -0
  138. package/payload/server/public/assets/clone-y8gexbBy.js +1 -0
  139. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-Br2gjtEO.js → cose-bilkent-S5V4N54A-CmkW2Eaj.js} +1 -1
  140. package/payload/server/public/assets/{dagre-DTjePoco.js → dagre-Dqp-ns8F.js} +1 -1
  141. package/payload/server/public/assets/{dagre-KV5264BT-DHBkRke4.js → dagre-KV5264BT-ZgWWXPLc.js} +1 -1
  142. package/payload/server/public/assets/data-gy6QH9c1.js +1 -0
  143. package/payload/server/public/assets/{diagram-5BDNPKRD-BIq1-idL.js → diagram-5BDNPKRD-CTX5-ScM.js} +1 -1
  144. package/payload/server/public/assets/{diagram-G4DWMVQ6-BsIUDzV6.js → diagram-G4DWMVQ6-BovIsO6H.js} +1 -1
  145. package/payload/server/public/assets/{diagram-MMDJMWI5-CgHSri2i.js → diagram-MMDJMWI5-DcETsQy-.js} +1 -1
  146. package/payload/server/public/assets/{diagram-TYMM5635-Ce2Wh9ZX.js → diagram-TYMM5635-yyq6peoZ.js} +1 -1
  147. package/payload/server/public/assets/{erDiagram-SMLLAGMA-BU0Kh6OQ.js → erDiagram-SMLLAGMA-CiNToftB.js} +1 -1
  148. package/payload/server/public/assets/{flatten-Bo6YRmWl.js → flatten-BtFI066E.js} +1 -1
  149. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B0N06MF7.js → flowDiagram-DWJPFMVM-Xnl3SpIM.js} +1 -1
  150. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BVbx4ARZ.js → ganttDiagram-T4ZO3ILL-C1iyWe0f.js} +1 -1
  151. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CNs-LD5i.js +1 -0
  152. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C-xRJ94t.js → gitGraphDiagram-UUTBAWPF-D97pbMQb.js} +1 -1
  153. package/payload/server/public/assets/graph-labels-cZu4pK16.js +1 -0
  154. package/payload/server/public/assets/{graph-g48ZcA5M.js → graph-qz5tFKqU.js} +3 -3
  155. package/payload/server/public/assets/{graphlib-YmNcoMjY.js → graphlib-Lq8ijgON.js} +1 -1
  156. package/payload/server/public/assets/info-OMHHGYJF-DsTNigSS.js +1 -0
  157. package/payload/server/public/assets/infoDiagram-42DDH7IO-C_OarRTA.js +2 -0
  158. package/payload/server/public/assets/{isEmpty-D6Kr-M1M.js → isEmpty-D6QovjYR.js} +1 -1
  159. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DTrq54yC.js → ishikawaDiagram-UXIWVN3A-B8XBdjJn.js} +1 -1
  160. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-OZZZMrFX.js → journeyDiagram-VCZTEJTY-CZYbiOaQ.js} +1 -1
  161. package/payload/server/public/assets/{kanban-definition-6JOO6SKY--w-IP9pN.js → kanban-definition-6JOO6SKY-B1PybFoh.js} +1 -1
  162. package/payload/server/public/assets/{line-Ckeulv5T.js → line-D-tw3hHp.js} +1 -1
  163. package/payload/server/public/assets/{linear-DOh_6k2k.js → linear-BHhXD3cd.js} +1 -1
  164. package/payload/server/public/assets/{mermaid-parser.core-CVRAxYRD.js → mermaid-parser.core-C9RAnysF.js} +2 -2
  165. package/payload/server/public/assets/{mermaid.core-B-mE18I1.js → mermaid.core-B532LT1r.js} +3 -3
  166. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-Bm8mDicL.js → mindmap-definition-QFDTVHPH-DGlgeeTV.js} +1 -1
  167. package/payload/server/public/assets/{ordinal-BDi6f4xk.js → ordinal-Bl-aM5b9.js} +1 -1
  168. package/payload/server/public/assets/packet-4T2RLAQJ-DGES22b-.js +1 -0
  169. package/payload/server/public/assets/pie-ZZUOXDRM-ChKeDbzt.js +1 -0
  170. package/payload/server/public/assets/{pieDiagram-DEJITSTG-BCmRLgGO.js → pieDiagram-DEJITSTG-DV9FIWko.js} +1 -1
  171. package/payload/server/public/assets/{public-DknO-g9S.js → public-Bu2_Xi0a.js} +5 -5
  172. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CniTIUTm.js → quadrantDiagram-34T5L4WZ-Betwya4l.js} +1 -1
  173. package/payload/server/public/assets/radar-PYXPWWZC-FGG5Fs7N.js +1 -0
  174. package/payload/server/public/assets/{reduce-CGi9ik8i.js → reduce-BD4xUd2c.js} +1 -1
  175. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CoxBSj9M.js → requirementDiagram-MS252O5E-Cq3vODdg.js} +1 -1
  176. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BjS-4jzq.js → sankeyDiagram-XADWPNL6-x8krXWcS.js} +1 -1
  177. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-B9jVOnPR.js → sequenceDiagram-FGHM5R23-i-_uH-Yl.js} +1 -1
  178. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BvOQPzP8.js → stateDiagram-FHFEXIEX-il4KqSgI.js} +1 -1
  179. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B6zNJ6Tv.js +1 -0
  180. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CdfgWLo1.js → timeline-definition-GMOUNBTQ-DATdZkA5.js} +1 -1
  181. package/payload/server/public/assets/treeView-SZITEDCU-VAQQdbtf.js +1 -0
  182. package/payload/server/public/assets/treemap-W4RFUUIX-DKchO3zI.js +1 -0
  183. package/payload/server/public/assets/useSelectionMode-A5KItZ2T.js +13 -0
  184. package/payload/server/public/assets/{brand-D0gNihp7.css → useSelectionMode-C-Ojh7W9.css} +1 -1
  185. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-JCgpIbj-.js → vennDiagram-DHZGUBPP-BJh9tJTt.js} +1 -1
  186. package/payload/server/public/assets/wardley-RL74JXVD-CBGtx0bS.js +1 -0
  187. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Dei3VqHo.js → wardleyDiagram-NUSXRM2D-EMN1Hdfg.js} +1 -1
  188. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DUtIyoIb.js → xychartDiagram-5P7HB3ND-DbUWXa7T.js} +1 -1
  189. package/payload/server/public/data.html +5 -5
  190. package/payload/server/public/graph.html +6 -6
  191. package/payload/server/public/index.html +5 -6
  192. package/payload/server/public/public.html +4 -5
  193. package/payload/server/server.js +65 -23
  194. package/payload/platform/plugins/admin/hooks/__tests__/insight.test.sh +0 -395
  195. package/payload/platform/plugins/admin/hooks/insight.sh +0 -219
  196. package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +0 -239
  197. package/payload/premium-plugins/writer-craft/hooks/__tests__/voice-session-end-text.test.sh +0 -284
  198. package/payload/premium-plugins/writer-craft/hooks/voice-session-end-text.sh +0 -75
  199. package/payload/premium-plugins/writer-craft/mcp/src/cli/ingest-session-text.ts +0 -65
  200. package/payload/server/public/assets/AdminShell-892Jy_rs.js +0 -1
  201. package/payload/server/public/assets/Checkbox-Bc2QzX9b.js +0 -1
  202. package/payload/server/public/assets/admin-D3K13ndi.js +0 -1
  203. package/payload/server/public/assets/architecture-YZFGNWBL--v-pJPNp.js +0 -1
  204. package/payload/server/public/assets/brand-CcN3dELF.js +0 -9
  205. package/payload/server/public/assets/channel-B1IT7to2.js +0 -1
  206. package/payload/server/public/assets/chunk-336JU56O-CdKRCIeE.js +0 -2
  207. package/payload/server/public/assets/chunk-426QAEUC-BybuQ3Ve.js +0 -1
  208. package/payload/server/public/assets/chunk-QZHKN3VN-Bd-GrQM6.js +0 -1
  209. package/payload/server/public/assets/classDiagram-6PBFFD2Q-rjCize6i.js +0 -1
  210. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BORWOUt0.js +0 -1
  211. package/payload/server/public/assets/clone-Csqv5U6T.js +0 -1
  212. package/payload/server/public/assets/data-Br-pdljK.js +0 -1
  213. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CI0s_tqn.js +0 -1
  214. package/payload/server/public/assets/graph-labels-BYH-IPCb.js +0 -1
  215. package/payload/server/public/assets/info-OMHHGYJF-g3gYW7Qm.js +0 -1
  216. package/payload/server/public/assets/infoDiagram-42DDH7IO-Di6oPQ_-.js +0 -2
  217. package/payload/server/public/assets/packet-4T2RLAQJ-CT0TB9HI.js +0 -1
  218. package/payload/server/public/assets/pie-ZZUOXDRM-CXLe7TFF.js +0 -1
  219. package/payload/server/public/assets/radar-PYXPWWZC-DnPLBl-D.js +0 -1
  220. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-v4ND10uR.js +0 -1
  221. package/payload/server/public/assets/treeView-SZITEDCU-C3cb7Xwe.js +0 -1
  222. package/payload/server/public/assets/treemap-W4RFUUIX-Dc7G3Bgm.js +0 -1
  223. package/payload/server/public/assets/useSelectionMode-DwsyptOw.js +0 -5
  224. package/payload/server/public/assets/wardley-RL74JXVD-DtgibWAt.js +0 -1
  225. /package/payload/server/public/assets/{_baseFor-Cam2PbSt.js → _baseFor-Cs8Y-rGh.js} +0 -0
  226. /package/payload/server/public/assets/{array-DYRGGQae.js → array-iHZP4KWJ.js} +0 -0
  227. /package/payload/server/public/assets/{cytoscape.esm-nWsJMTNI.js → cytoscape.esm-BR2GOQ8_.js} +0 -0
  228. /package/payload/server/public/assets/{defaultLocale-Du1XY3Dp.js → defaultLocale-B9aLeOTg.js} +0 -0
  229. /package/payload/server/public/assets/{dist-BzAsli7o.js → dist-DB-VPj_8.js} +0 -0
  230. /package/payload/server/public/assets/{init-B5BXBRcm.js → init-BNFRgqHM.js} +0 -0
  231. /package/payload/server/public/assets/{katex-HOUACuRw.js → katex-B-EfS3nw.js} +0 -0
  232. /package/payload/server/public/assets/{path-CNO468J-.js → path-DmWWdwp7.js} +0 -0
  233. /package/payload/server/public/assets/{rough.esm-DRO6hWPh.js → rough.esm-Ci7Kjt46.js} +0 -0
  234. /package/payload/server/public/assets/{src-CWiyyVfn.js → src-C1jfwBq0.js} +0 -0
@@ -1,127 +1,59 @@
1
1
  /**
2
- * voice-ingest-session-text — extract operator turns from a Claude Code
3
- * session JSONL and write them as :Message {format:'text', source:'admin-pty'}
4
- * corpus nodes.
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
- * Called by the SessionEnd hook (via the CLI wrapper) after each admin PTY
7
- * session. Re-running against the same JSONL is a no-op — MERGE on
8
- * (contentHash, accountId) is the deduplication primitive.
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
- * JSONL record shape expected (Claude Code session format):
14
- * { "type": "user" | "assistant", "message": { "role": "...", "content": ... }, ... }
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
- * Extracts text content from a "real operator" user record.
31
- * Returns null when the record should be skipped.
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 extractOperatorText(record) {
34
- if (!record || typeof record !== "object")
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
- text = text.trim();
71
- if (text.length === 0)
32
+ const trimmed = text.trim();
33
+ if (trimmed.length === 0)
72
34
  return null;
73
- // Exclusions.
74
- if (text.startsWith("/"))
35
+ if (trimmed.startsWith("/"))
75
36
  return null; // slash command
76
- if (text.includes("<system-reminder>"))
37
+ if (trimmed.includes("<system-reminder>"))
77
38
  return null; // harness injection
78
- if (text.length >= 4096)
39
+ if (trimmed.length >= 4096)
79
40
  return null; // paste block
80
- return text;
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 { sessionJsonlPath, accountId, userId, sessionId = null } = params;
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 (!sessionJsonlPath) {
116
- throw new Error("voice-ingest-session-text: sessionJsonlPath required");
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
- catch (err) {
124
- throw new Error(`voice-ingest-session-text: failed to read JSONL at '${sessionJsonlPath}': ${err instanceof Error ? err.message : String(err)}`);
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`);
@@ -1 +1 @@
1
- {"version":3,"file":"voice-ingest-session-text.js","sourceRoot":"","sources":["../../src/tools/voice-ingest-session-text.ts"],"names":[],"mappings":"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"}
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: extractOperatorTurns() extracts real turns
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, writeFileSync, mkdtempSync, rmSync } from "node:fs";
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.extractOperatorTurns, "function");
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: JSONL extraction (no DB required).
295
+ // 7. voice-ingest-session-text: operator-turn filter (no DB required).
298
296
  // ---------------------------------------------------------------------------
299
- console.log("\n-- JSONL extraction --");
297
+ console.log("\n-- operator-turn filter --");
300
298
 
301
- function makeJsonlLine(type, role, content) {
302
- return JSON.stringify({ type, message: { role, content } });
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("extractOperatorText: system-reminder is excluded", () => {
315
- const record = {
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("extractOperatorText: paste block > 4096 chars is excluded", () => {
322
- const record = {
323
- type: "user",
324
- message: { role: "user", content: "x".repeat(4097) },
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("extractOperatorText: paste block = 4096 chars is excluded", () => {
329
- const record = {
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("extractOperatorText: paste block = 4095 chars is included", () => {
336
- const body = "x".repeat(4095);
337
- const record = { type: "user", message: { role: "user", content: body } };
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("extractOperatorText: assistant turn is excluded", () => {
341
- const record = { type: "assistant", message: { role: "assistant", content: "Reply" } };
342
- assert.equal(ingestMod.extractOperatorText(record), null);
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("extractOperatorText: tool_result-only content is excluded", () => {
345
- const record = {
346
- type: "user",
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
- // Full JSONL fixture: 3 real turns + 2 assistant + 1 slash + 1 system-reminder.
366
- // Expected: extractOperatorTurns returns 3 strings.
327
+ // turns-array semantics: a mixed array filters down to the real turns.
367
328
  await check(
368
- "extractOperatorTurns: fixture with 3 real turns + 4 excluded → 3 results",
369
- async () => {
370
- const tmp = mkdtempSync(join(tmpdir(), "smoke-ingest-"));
371
- const jsonlPath = join(tmp, "session.jsonl");
372
- const lines = [
373
- // 3 real operator turns
374
- makeJsonlLine("user", "user", "First real turn"),
375
- makeJsonlLine("user", "user", "Second real turn"),
376
- makeJsonlLine("user", "user", "Third real turn"),
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
- writeFileSync(jsonlPath, lines.join("\n") + "\n");
386
- try {
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
- "Ingest operator PTY turns from a Claude Code session JSONL as :Message {format:'text', source:'admin-pty', authorshipMode:'human-only'} corpus nodes. Deduplication via SHA256 contentHash — re-running against the same JSONL is a no-op. Triggers voice-distil-profile {format:'text'} after ingest (cadence guard decides whether distillation runs). Called automatically by the SessionEnd hook; can also be invoked manually.",
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
- sessionJsonlPath: z.string().min(1).describe("Absolute path to the Claude Code session JSONL file"),
354
- sessionId: z.string().optional().describe("Session ID for provenance; read from the SessionEnd envelope"),
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 ({ sessionJsonlPath, sessionId, userId }) => {
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
- sessionJsonlPath,
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` (SessionEnd ingest). The single
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 — extract operator turns from a Claude Code
3
- * session JSONL and write them as :Message {format:'text', source:'admin-pty'}
4
- * corpus nodes.
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
- * Called by the SessionEnd hook (via the CLI wrapper) after each admin PTY
7
- * session. Re-running against the same JSONL is a no-op — MERGE on
8
- * (contentHash, accountId) is the deduplication primitive.
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
- * JSONL record shape expected (Claude Code session format):
14
- * { "type": "user" | "assistant", "message": { "role": "...", "content": ... }, ... }
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
- sessionJsonlPath: string;
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
- * Extracts text content from a "real operator" user record.
45
- * Returns null when the record should be skipped.
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 async function extractOperatorTurns(jsonlPath: string): Promise<string[]> {
100
- const turns: string[] = [];
101
-
102
- const rl = createInterface({
103
- input: createReadStream(jsonlPath, { encoding: "utf-8" }),
104
- crlfDelay: Infinity,
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 { sessionJsonlPath, accountId, userId, sessionId = null } = params;
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 (!sessionJsonlPath) {
134
- throw new Error("voice-ingest-session-text: sessionJsonlPath required");
61
+ if (!Array.isArray(turns)) {
62
+ throw new Error("voice-ingest-session-text: turns array required");
135
63
  }
136
64
 
137
- // 1. Extract operator turns from the JSONL.
138
- let allTurns: string[];
139
- try {
140
- allTurns = await extractOperatorTurns(sessionJsonlPath);
141
- } catch (err) {
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) {