@tequila99/githuman 0.11.2 → 0.12.0
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/README.md +62 -2
- package/dist/cli/commands/mcp.js +112 -0
- package/dist/cli/commands/pi-acp.js +21 -0
- package/dist/cli/config.js +7 -1
- package/dist/cli/index.js +19 -8
- package/dist/cli/server-runtime.js +1 -0
- package/dist/server/adapters/agents/artifact-permission.js +88 -0
- package/dist/server/adapters/pi-acp/agent.js +98 -0
- package/dist/server/adapters/pi-acp/compatibility.js +57 -0
- package/dist/server/adapters/pi-acp/control.js +76 -0
- package/dist/server/adapters/pi-acp/errors.js +17 -0
- package/dist/server/adapters/pi-acp/extension.js +255 -0
- package/dist/server/adapters/pi-acp/launch.js +16 -0
- package/dist/server/adapters/pi-acp/mcp.js +153 -0
- package/dist/server/adapters/pi-acp/process.js +199 -0
- package/dist/server/adapters/pi-acp/session.js +409 -0
- package/dist/server/adapters/pi-acp/vendor/LICENSE +21 -0
- package/dist/server/adapters/pi-acp/vendor/README.md +29 -0
- package/dist/server/adapters/pi-acp/vendor/prompt.js +56 -0
- package/dist/server/app.js +92 -5
- package/dist/server/config/agents.js +4 -6
- package/dist/server/db/artifact-graph-migrations.js +56 -0
- package/dist/server/db/artifact-migrations.js +70 -0
- package/dist/server/db/artifact-review-migrations.js +24 -0
- package/dist/server/db/artifact-search-migrations.js +31 -0
- package/dist/server/db/artifact-validation-migrations.js +70 -0
- package/dist/server/db/index.js +3 -0
- package/dist/server/db/migrations.js +10 -0
- package/dist/server/db/sqlite-error.js +15 -0
- package/dist/server/db/transaction.js +40 -0
- package/dist/server/errors/artifacts.js +28 -0
- package/dist/server/errors/database.js +2 -0
- package/dist/server/hooks/access/require-access.js +8 -0
- package/dist/server/repositories/artifact-catalog.repo.js +283 -0
- package/dist/server/repositories/artifact-files.repo.js +181 -0
- package/dist/server/repositories/artifact-graph.repo.js +50 -0
- package/dist/server/repositories/artifact-search.repo.js +192 -0
- package/dist/server/repositories/artifact-transition.repo.js +85 -0
- package/dist/server/repositories/artifact-validation.repo.js +146 -0
- package/dist/server/repositories/notes-catalog.repo.js +2 -10
- package/dist/server/repositories/task.repo.js +114 -0
- package/dist/server/routes/agent.js +8 -1
- package/dist/server/routes/artifact-actions.js +129 -0
- package/dist/server/routes/artifact-agent.js +183 -0
- package/dist/server/routes/artifact-definitions.js +163 -0
- package/dist/server/routes/artifact-transitions.js +80 -0
- package/dist/server/routes/artifacts.js +111 -0
- package/dist/server/routes/events.js +5 -1
- package/dist/server/services/agent/agent-session.js +180 -10
- package/dist/server/services/agent/context-builder.js +30 -2
- package/dist/server/services/agent/session-registry.js +106 -2
- package/dist/server/services/agent/turn-task-context.js +1 -0
- package/dist/server/services/artifact-authorization.service.js +174 -0
- package/dist/server/services/artifact-definition.service.js +96 -0
- package/dist/server/services/artifact-export.service.js +44 -0
- package/dist/server/services/artifact-graph-validation.js +497 -0
- package/dist/server/services/artifact-graph.service.js +81 -0
- package/dist/server/services/artifact-lifecycle.service.js +343 -0
- package/dist/server/services/artifact-maintenance.service.js +55 -0
- package/dist/server/services/artifact-search.service.js +331 -0
- package/dist/server/services/artifact-storage.service.js +646 -0
- package/dist/server/services/artifact-transition.service.js +607 -0
- package/dist/server/services/artifact-type.service.js +74 -0
- package/dist/server/services/artifact-validation-jobs.service.js +518 -0
- package/dist/server/services/device-connections.js +9 -1
- package/dist/server/services/review.service.js +6 -5
- package/dist/server/services/task.service.js +225 -0
- package/dist/server/utils/artifact-actor.js +13 -0
- package/dist/server/utils/artifact-page.js +42 -0
- package/dist/server/utils/take-within-bytes.js +16 -0
- package/dist/server/utils/text.js +7 -0
- package/dist/shared/agents/schemas.js +27 -0
- package/dist/shared/app/storage-constants.js +2 -0
- package/dist/shared/artifact-tools/descriptions.js +11 -0
- package/dist/shared/artifact-tools/instructions.js +14 -0
- package/dist/shared/artifact-tools/schemas.js +119 -0
- package/dist/shared/artifact-transitions/constants.js +21 -0
- package/dist/shared/artifact-transitions/schemas.js +111 -0
- package/dist/shared/artifact-transitions/transitions.js +61 -0
- package/dist/shared/artifact-transitions/types.js +1 -0
- package/dist/shared/artifacts/constants.js +34 -0
- package/dist/shared/artifacts/mcp-constants.js +24 -0
- package/dist/shared/artifacts/normalize.js +9 -0
- package/dist/shared/artifacts/schemas.js +820 -0
- package/dist/shared/artifacts/search.js +101 -0
- package/dist/shared/artifacts/types.js +1 -0
- package/dist/shared/events/schemas.js +1 -1
- package/dist/shared/events/types.js +1 -0
- package/dist/shared/tasks/schemas.js +261 -0
- package/dist/shared/tasks/types.js +1 -0
- package/dist/shared/utils/artifact-body.js +10 -0
- package/dist/shared/utils/canonical-json.js +22 -0
- package/dist/shared/utils/is-safe-prefixed-filename.js +10 -0
- package/dist/shared/utils/is-uuid.js +4 -2
- package/dist/shared/utils/is-valid-artifact-type-id.js +9 -0
- package/dist/shared/utils/is-valid-filename-prefix.js +13 -0
- package/dist/web/assets/AccessPage-Dvj0aCkm.js +1 -0
- package/dist/web/assets/AddButton-CMC9qf51.js +4 -0
- package/dist/web/assets/AddToAgentButton-BitTdCEg.js +1 -0
- package/dist/web/assets/AppPage-Cozv2vqG.js +1 -0
- package/dist/web/assets/ArtifactDefinitionPicker-BQOoU60k.js +3 -0
- package/dist/web/assets/ArtifactDefinitionPicker-D3qdrxlC.css +1 -0
- package/dist/web/assets/ArtifactsPage-BJR-XYYs.js +2 -0
- package/dist/web/assets/ArtifactsPage-Cu1xdYNf.css +1 -0
- package/dist/web/assets/CancelButton-mkxRHwoZ.js +1 -0
- package/dist/web/assets/ClosePopup-BtDeDZsk.js +1 -0
- package/dist/web/assets/CreateButton-zCmb7snC.js +1 -0
- package/dist/web/assets/CreateReviewFabButton-BCg1TvFh.js +1 -0
- package/dist/web/assets/DialogHeader-CPL9OtDV.css +1 -0
- package/dist/web/assets/DialogHeader-CQvAZVx7.js +1 -0
- package/dist/web/assets/{ErrorNotFound-DucDzOUJ.js → ErrorNotFound-fXS367lZ.js} +1 -1
- package/dist/web/assets/{IndexPage-D5PvyGrX.css → IndexPage-5V5GLtgi.css} +1 -1
- package/dist/web/assets/IndexPage-DMTZyWQA.js +1 -0
- package/dist/web/assets/MainLayout-DWJ_-EMV.js +7 -0
- package/dist/web/assets/MainLayout-Dy74m_q1.css +1 -0
- package/dist/web/assets/NoteVisualEditor-5rHBQ3j0.js +1054 -0
- package/dist/web/assets/{NoteVisualEditor-CawpxEFB.css → NoteVisualEditor-DE4ACTRJ.css} +1 -1
- package/dist/web/assets/NotesPage-C_eoCUl7.css +1 -0
- package/dist/web/assets/NotesPage-CjaxjLBW.js +4 -0
- package/dist/web/assets/{PdfPreview-rlkcqoMF.js → PdfPreview-2NQ5gkjh.js} +2 -2
- package/dist/web/assets/ProjectFilePage-B-WUUxnq.js +1 -0
- package/dist/web/assets/QBtn-V3VXtJXi.js +1 -0
- package/dist/web/assets/QFab-CxpedhPI.js +1 -0
- package/dist/web/assets/{QForm-Be8-ucuJ.js → QForm-ClpSneeD.js} +1 -1
- package/dist/web/assets/QInput-BnqLJGXl.js +1 -0
- package/dist/web/assets/QScrollArea-js5dkUz1.js +1 -0
- package/dist/web/assets/QSpace-C7iAnGlU.js +1 -0
- package/dist/web/assets/QTabs-DIy5gWMb.js +1 -0
- package/dist/web/assets/QVirtualScroll-DkD0TczV.js +1 -0
- package/dist/web/assets/ReviewDetailPage-BgxcsTqY.css +1 -0
- package/dist/web/assets/ReviewDetailPage-Bmc8DmSu.js +1 -0
- package/dist/web/assets/ReviewsPage-DR1IWCmu.js +1 -0
- package/dist/web/assets/SearchInput-BRyN93Z1.js +1 -0
- package/dist/web/assets/StatusSwitcher-CpkH8BuC.js +1 -0
- package/dist/web/assets/{StatusSwitcher-D6i8_OfR.css → StatusSwitcher-DaE1ufAA.css} +1 -1
- package/dist/web/assets/TagFilterField-Bl3FBkB5.js +1 -0
- package/dist/web/assets/TagFilterField-DjUH0m3_.css +1 -0
- package/dist/web/assets/{TerminalView-617DZuPt.css → TerminalView-BCeke4xd.css} +1 -1
- package/dist/web/assets/{TerminalView-D4elkzN4.js → TerminalView-tEyLM5qZ.js} +12 -12
- package/dist/web/assets/{abnfDiagram-O67JEVCF-Cugru96L.js → abnfDiagram-O67JEVCF-DN9xiV9p.js} +1 -1
- package/dist/web/assets/{access-store-Cdg8oRAM.js → access-store-CwkOl71l.js} +1 -1
- package/dist/web/assets/{agent-store-D_W7iD_B.js → agent-store-Grbx4jkz.js} +5 -5
- package/dist/web/assets/architecture-7GRP2DOG-DmaYCP8T.js +1 -0
- package/dist/web/assets/{architectureDiagram-NJMV4G6O-7rMsE4Wt.js → architectureDiagram-NJMV4G6O-BVAJOucG.js} +1 -1
- package/dist/web/assets/{blockDiagram-BEXU5L5S-BvSnwUrI.js → blockDiagram-BEXU5L5S-TJAfSX44.js} +1 -1
- package/dist/web/assets/{c4Diagram-YGBWAQC7-CgmQlCVx.js → c4Diagram-YGBWAQC7-5UHyT_tW.js} +1 -1
- package/dist/web/assets/channel-B4_5H-fb.js +1 -0
- package/dist/web/assets/{chunk-3FUC2YCW-_i8udThz.js → chunk-3FUC2YCW-CelgLyJi.js} +1 -1
- package/dist/web/assets/{chunk-5DYCD2WN-Mhk2LlLk.js → chunk-5DYCD2WN-bhEAVIbQ.js} +1 -1
- package/dist/web/assets/{chunk-742MDFTN-CDVcwgEp.js → chunk-742MDFTN-ByLz4EcD.js} +1 -1
- package/dist/web/assets/{chunk-7INBJB4K-C2c1fi9s.js → chunk-7INBJB4K-CK2i0csa.js} +1 -1
- package/dist/web/assets/{chunk-7M6MHVWA-BeGkoIBL.js → chunk-7M6MHVWA-CoCiujjC.js} +1 -1
- package/dist/web/assets/{chunk-7PRAP22T-BVWTh9sT.js → chunk-7PRAP22T-CY4NCrCY.js} +1 -1
- package/dist/web/assets/{chunk-GTNCS2PH-gVhX7NZP.js → chunk-GTNCS2PH-DMB7bQGB.js} +1 -1
- package/dist/web/assets/{chunk-GWA4HPMP-BPdnIcQH.js → chunk-GWA4HPMP-F6qclPTR.js} +1 -1
- package/dist/web/assets/{chunk-MBY4JIJT-B2VfO_06.js → chunk-MBY4JIJT-CSiiBtlX.js} +1 -1
- package/dist/web/assets/{chunk-NETBCI7D-DZF_gITO.js → chunk-NETBCI7D-CBh7GChL.js} +1 -1
- package/dist/web/assets/{chunk-O7XYJQB3-CDpBWiLq.js → chunk-O7XYJQB3-B2aqz0sN.js} +1 -1
- package/dist/web/assets/{chunk-UA2S7LBM-Iv7TSRE_.js → chunk-UA2S7LBM-B_-P_eR0.js} +1 -1
- package/dist/web/assets/{chunk-WEXAMYUT-Ce6goZ2Y.js → chunk-WEXAMYUT-19nMFxzK.js} +1 -1
- package/dist/web/assets/{chunk-Z7XXMR3K-CY6E6_Ux.js → chunk-Z7XXMR3K-Co7gzRY1.js} +1 -1
- package/dist/web/assets/{chunk-ZIGJFQKS-BLzsXZBc.js → chunk-ZIGJFQKS-Eoi4K5bK.js} +1 -1
- package/dist/web/assets/{classDiagram-v2-NBCMYWYE-Dz0kD9P6.js → classDiagram-v2-NBCMYWYE-CfFGzL-A.js} +1 -1
- package/dist/web/assets/copy-code-DaqEfdXL.js +1 -0
- package/dist/web/assets/create-DedXY-KP.js +1 -0
- package/dist/web/assets/{cynefin-OW5HDTMX-DWIx3wRm.js → cynefin-OW5HDTMX-DdZXl3KU.js} +1 -1
- package/dist/web/assets/{cynefinDiagram-VND7K2PF-2D80uocv.js → cynefinDiagram-VND7K2PF-WU21nYH-.js} +1 -1
- package/dist/web/assets/{dagre-6A5THRUB-BLBhukn-.js → dagre-6A5THRUB-48z3F8Pl.js} +1 -1
- package/dist/web/assets/date-DZIuZp-w.js +1 -0
- package/dist/web/assets/{devices-store-BfZKPOhg.js → devices-store-Bfk2wdrQ.js} +1 -1
- package/dist/web/assets/{diagram-22UHCM2B-DY8dMLZ3.js → diagram-22UHCM2B-B0AZgJW9.js} +1 -1
- package/dist/web/assets/{diagram-3UASUU5V-Bf6Od1NH.js → diagram-3UASUU5V-CzEzrxuO.js} +1 -1
- package/dist/web/assets/{diagram-ATOU4E4O-CjLGcYD5.js → diagram-ATOU4E4O-w6h1bD3w.js} +1 -1
- package/dist/web/assets/{diagram-CDSNMT55-gIvaVNvs.js → diagram-CDSNMT55-BdTHQd_o.js} +1 -1
- package/dist/web/assets/{diagram-MLGK6HIB-VR5kiCi5.js → diagram-MLGK6HIB-pB4cj6c2.js} +1 -1
- package/dist/web/assets/{diagram-MPIPVDR6-CdAdj25I.js → diagram-MPIPVDR6-C7C06qyV.js} +1 -1
- package/dist/web/assets/diff-store-DBDL5Hw5.js +93 -0
- package/dist/web/assets/{dist-lgw4kcVA.js → dist-B7Cu0FBW.js} +1 -1
- package/dist/web/assets/{dist-yzAhvE-V.js → dist-B8i8y3GY.js} +1 -1
- package/dist/web/assets/{dist-C85t5q3z.js → dist-BNgPhnKo.js} +1 -1
- package/dist/web/assets/{dist-CEl-Ko94.js → dist-BWoPV5P3.js} +1 -1
- package/dist/web/assets/{dist-DLuI1PxH.js → dist-CJ7isxli.js} +1 -1
- package/dist/web/assets/{dist-joQDFmfy.js → dist-CTJJYvYG.js} +1 -1
- package/dist/web/assets/{dist-CBGyhCYv.js → dist-CZz0KXAA.js} +1 -1
- package/dist/web/assets/{dist-CIMEaJAX.js → dist-DNpwgDba.js} +1 -1
- package/dist/web/assets/{dist-CTd7Kuqx.js → dist-DWCdhk-O.js} +1 -1
- package/dist/web/assets/{dist-BU8erXQF.js → dist-DqSUdjG9.js} +1 -1
- package/dist/web/assets/{dist-C54FrSb8.js → dist-Dy9K9LOR.js} +1 -1
- package/dist/web/assets/{ebnfDiagram-ZINNZB2B-irTAlMFO.js → ebnfDiagram-ZINNZB2B-75vt7539.js} +1 -1
- package/dist/web/assets/{elk-276RUBZZ-Dj5ligvC.js → elk-276RUBZZ-DXDjJVTy.js} +1 -1
- package/dist/web/assets/{erDiagram-OPXOYQCR-Bvn6rbL1.js → erDiagram-OPXOYQCR-tNNInTmk.js} +1 -1
- package/dist/web/assets/eventmodeling-NTZA5JFV-QMRehQtM.js +1 -0
- package/dist/web/assets/flowDiagram-KWPJA3E3-DJAgsbXC.js +1 -0
- package/dist/web/assets/{ganttDiagram-FUAMR5RP-BNGAUF5H.js → ganttDiagram-FUAMR5RP-h3E8lnCd.js} +1 -1
- package/dist/web/assets/{gitGraph-4MIJSDKK-DYSHOl72.js → gitGraph-4MIJSDKK-BUwY-iv2.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-X574FWY7-BGwRHrPq.js → gitGraphDiagram-X574FWY7-C0AgQH5k.js} +1 -1
- package/dist/web/assets/i18n-CfTd46OX.js +1 -0
- package/dist/web/assets/icons-BoaZfGBj.js +1 -0
- package/dist/web/assets/index-BQU3KK1E.css +1 -0
- package/dist/web/assets/index-BTpokWxr.js +2 -0
- package/dist/web/assets/{info-A6RAGUB7-DNWR20pW.js → info-A6RAGUB7-DVMZ4hdK.js} +1 -1
- package/dist/web/assets/{infoDiagram-VRGFBTTK-BhNwJLY5.js → infoDiagram-VRGFBTTK-kLaGXGQ2.js} +1 -1
- package/dist/web/assets/{init-app-cg-B_TFN.js → init-app-Bxc_l2yT.js} +1 -1
- package/dist/web/assets/{is-D0waCELe.js → is-B1kBQ5Va.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-CSkDpn64.js → ishikawaDiagram-OU5B5YK6-Oj7bZlyo.js} +1 -1
- package/dist/web/assets/{journeyDiagram-ZHPQQLJL-D2CEecC3.js → journeyDiagram-ZHPQQLJL-BG7V2Srs.js} +1 -1
- package/dist/web/assets/{kanban-definition-PNTS6WVX-CQHlo4Hh.js → kanban-definition-PNTS6WVX-CIJiDE6d.js} +1 -1
- package/dist/web/assets/{line-C-izH1ks.js → line-D2vEKYRZ.js} +1 -1
- package/dist/web/assets/markdown-Bm2wfvok.js +16 -0
- package/dist/web/assets/mdi-Byw1NZrZ.js +1 -0
- package/dist/web/assets/{mermaid-parser.core-CAGwq6D-.js → mermaid-parser.core-BcBEWjW6.js} +3 -3
- package/dist/web/assets/{mermaid.core--xlI_0tK.js → mermaid.core-DobO0deo.js} +4 -4
- package/dist/web/assets/{mindmap-definition-NLK3R4M7-BuCxhlwy.js → mindmap-definition-NLK3R4M7-y7Qz5gBF.js} +1 -1
- package/dist/web/assets/{packet-AYTQ26CC-Bi7x5lJK.js → packet-AYTQ26CC-oRQgKr9d.js} +1 -1
- package/dist/web/assets/{pegDiagram-GJSIUBJH-qWzBPkCQ.js → pegDiagram-GJSIUBJH-RIU8XOHq.js} +1 -1
- package/dist/web/assets/{pie-WAS4IAKB-Di0wC4XB.js → pie-WAS4IAKB-qmOlsLkx.js} +1 -1
- package/dist/web/assets/{pieDiagram-5QR66LMP-BCDVY9q2.js → pieDiagram-5QR66LMP-BM932TDA.js} +1 -1
- package/dist/web/assets/pinia-BfqEuvsi.js +1 -0
- package/dist/web/assets/pinia-Cmp1GI8k.js +1 -0
- package/dist/web/assets/preview-store-D7qF6SgX.js +2 -0
- package/dist/web/assets/{project-files-store-byqyG2ts.js → project-files-store-OhGs_H7U.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-O4NWA36T-CpFObUjT.js → quadrantDiagram-O4NWA36T-qQZYwTy7.js} +1 -1
- package/dist/web/assets/{radar-RG4KPBEZ-Br8yH8rq.js → radar-RG4KPBEZ-Kdglk6eY.js} +1 -1
- package/dist/web/assets/{railroad-74A4TZTK-CACSqhA-.js → railroad-74A4TZTK-kVhMYx4I.js} +1 -1
- package/dist/web/assets/railroad-abnf-HS5TGJTU-MiKgjOXr.js +1 -0
- package/dist/web/assets/railroad-ebnf-LZEXJU2U-BFL9h7Zx.js +1 -0
- package/dist/web/assets/railroad-peg-WCYAUIDC-ChGGfIn7.js +1 -0
- package/dist/web/assets/{railroadDiagram-XR7U4H2S-sYXRKGK1.js → railroadDiagram-XR7U4H2S-K9SrOGcT.js} +1 -1
- package/dist/web/assets/{render-C7fu7uYY.js → render-Brao9Nj2.js} +1 -1
- package/dist/web/assets/repository-store-DZgQ5H7J.js +1 -0
- package/dist/web/assets/{requirementDiagram-PLB6GJNP-C9I1JbQc.js → requirementDiagram-PLB6GJNP-CtA9ZKEx.js} +1 -1
- package/dist/web/assets/runtime-core.esm-bundler-DDnHUoIy.js +1 -0
- package/dist/web/assets/{safe-storage-C76bPypO.js → safe-storage-CvVvrm4v.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-IPEJSGJF-CuvFQhPh.js → sankeyDiagram-IPEJSGJF-BH_t4exx.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-PO4LG4MO-CaVb9Y6e.js → sequenceDiagram-PO4LG4MO-hPNPqpDa.js} +1 -1
- package/dist/web/assets/single-flight-CyDZB3rb.js +1 -0
- package/dist/web/assets/{stateDiagram-v2-GCMORJYK-Dp_APryr.js → stateDiagram-v2-GCMORJYK-BVmjZDRD.js} +1 -1
- package/dist/web/assets/{swimlanes-2SLR337P-FclUI-k0.js → swimlanes-2SLR337P-Tgk8-6jj.js} +1 -1
- package/dist/web/assets/swimlanesDiagram-TC7HE7FX-W1zDrK61.js +8 -0
- package/dist/web/assets/{terminal-store-BnEkXuBj.js → terminal-store-CKgJjtC6.js} +1 -1
- package/dist/web/assets/theme-slSxLNv6.js +1 -0
- package/dist/web/assets/{timeline-definition-EJHVYXUP-BAqwqj3c.js → timeline-definition-EJHVYXUP-lAIHEGe8.js} +1 -1
- package/dist/web/assets/{treeView-Q6P3EWNA-D87jJbUQ.js → treeView-Q6P3EWNA-CdvzKtWf.js} +1 -1
- package/dist/web/assets/{treemap-WGGIJYW6-B6nhGhRc.js → treemap-WGGIJYW6-BxDSJfrJ.js} +1 -1
- package/dist/web/assets/use-add-agent-context-BSHGL5iV.js +1 -0
- package/dist/web/assets/use-app-theme-fmVV2QM8.js +1 -0
- package/dist/web/assets/use-countdown-D6_qSOZJ.js +1 -0
- package/dist/web/assets/use-notify-error-Dx2D9IEP.js +1 -0
- package/dist/web/assets/{use-panel-width-CjSWCFr4.js → use-panel-width-BYOPuHat.js} +1 -1
- package/dist/web/assets/use-router-link-D7geCGQI.js +1 -0
- package/dist/web/assets/use-row-height-BK8kNihW.js +1 -0
- package/dist/web/assets/use-server-events-CvcbsbIf.js +1 -0
- package/dist/web/assets/use-virtual-scroll-DixIsJk4.js +1 -0
- package/dist/web/assets/{use-workspace-navigation-CnebLvBV.js → use-workspace-navigation-AaRMWmjQ.js} +1 -1
- package/dist/web/assets/{usecaseDiagram-POWQR4AR-7YcIKxAb.js → usecaseDiagram-POWQR4AR-BH3KvMpz.js} +1 -1
- package/dist/web/assets/{vennDiagram-UO4OBE2U-BZq5cFC4.js → vennDiagram-UO4OBE2U-Dfi-raKp.js} +1 -1
- package/dist/web/assets/viewport-store-NqQS7itT.js +1 -0
- package/dist/web/assets/{vue-i18n.runtime-CEtihHHL.js → vue-i18n.runtime-JOo8b7-t.js} +2 -2
- package/dist/web/assets/{wardley-WFR3VGLG-BT8YO9H4.js → wardley-WFR3VGLG-DmbtSM24.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-VNRHLVJA-rDpXFf6D.js → wardleyDiagram-VNRHLVJA-DIzhGvI7.js} +1 -1
- package/dist/web/assets/weighted-lru-BFtZKA_y.js +1 -0
- package/dist/web/assets/workspace-navigation-xfxULfM7.js +1 -0
- package/dist/web/assets/{xychartDiagram-PMCCYNJV-ClniUuZc.js → xychartDiagram-PMCCYNJV-XgqSHH_N.js} +1 -1
- package/dist/web/index.html +9 -9
- package/package.json +5 -3
- package/dist/web/assets/AccessPage-CX3w30zw.js +0 -1
- package/dist/web/assets/AppPage-PFJG281y.js +0 -1
- package/dist/web/assets/CreateButton-Ch0b7juj.js +0 -1
- package/dist/web/assets/CreateReviewFabButton-DTuJzw3q.js +0 -1
- package/dist/web/assets/IndexPage-tgW07Qvs.js +0 -1
- package/dist/web/assets/MainLayout-C6yBhQnf.css +0 -1
- package/dist/web/assets/MainLayout-Cw4jpB1x.js +0 -8
- package/dist/web/assets/NoteVisualEditor-DiGhLhQg.js +0 -1054
- package/dist/web/assets/NotesPage-CVyVr9tl.js +0 -4
- package/dist/web/assets/NotesPage-CxGnZuVQ.css +0 -1
- package/dist/web/assets/PanelResize-B6FP9ZVB.js +0 -1
- package/dist/web/assets/ProjectFilePage-CkxfX9b1.js +0 -1
- package/dist/web/assets/QBtn-CyyV1Bx_.js +0 -1
- package/dist/web/assets/QExpansionItem-Dp9lbdVb.js +0 -4
- package/dist/web/assets/QFab-LOmZ9rev.js +0 -1
- package/dist/web/assets/QInput-Dq6131uz.js +0 -1
- package/dist/web/assets/QSelect-B34OqtIH.js +0 -1
- package/dist/web/assets/QSpace-BhOVGpQh.js +0 -1
- package/dist/web/assets/QVirtualScroll-BYgJ1Kh2.js +0 -1
- package/dist/web/assets/ReviewDetailPage-CkCilMNW.css +0 -1
- package/dist/web/assets/ReviewDetailPage-GNjBa4X0.js +0 -1
- package/dist/web/assets/ReviewsPage-An5fRS92.js +0 -1
- package/dist/web/assets/StatusSwitcher-DrFHHwGm.js +0 -1
- package/dist/web/assets/architecture-7GRP2DOG-BPCNj4lR.js +0 -1
- package/dist/web/assets/channel-CzRYxuLe.js +0 -1
- package/dist/web/assets/create-B9Tn5Xvi.js +0 -1
- package/dist/web/assets/diff-store-B4adGxC2.js +0 -93
- package/dist/web/assets/eventmodeling-NTZA5JFV-BJsTZ_nG.js +0 -1
- package/dist/web/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNa-Dr0goTwe.woff +0 -0
- package/dist/web/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ-D-x-0Q06.woff2 +0 -0
- package/dist/web/assets/flowDiagram-KWPJA3E3-CvXh1Df7.js +0 -1
- package/dist/web/assets/i18n-DnlAcIbT.js +0 -1
- package/dist/web/assets/index-Cw7GJi3K.js +0 -2
- package/dist/web/assets/index-wsOPzloa.css +0 -1
- package/dist/web/assets/markdown-CvtLTiBZ.js +0 -16
- package/dist/web/assets/pinia-DO0AdKGg.js +0 -1
- package/dist/web/assets/pinia-uOZCmBi-.js +0 -1
- package/dist/web/assets/preview-store-DyO8G-ox.js +0 -1
- package/dist/web/assets/railroad-abnf-HS5TGJTU-DTBsRB1c.js +0 -1
- package/dist/web/assets/railroad-ebnf-LZEXJU2U-D3mrY4ar.js +0 -1
- package/dist/web/assets/railroad-peg-WCYAUIDC-33ZjWX0u.js +0 -1
- package/dist/web/assets/repository-store-DtRDth1L.js +0 -1
- package/dist/web/assets/runtime-core.esm-bundler-CAvPiMpd.js +0 -1
- package/dist/web/assets/single-flight-fPyIy7h5.js +0 -1
- package/dist/web/assets/swimlanesDiagram-TC7HE7FX-CuUvsn0e.js +0 -8
- package/dist/web/assets/theme-CnbaLamF.js +0 -1
- package/dist/web/assets/use-add-agent-context-xHAjjOf1.js +0 -1
- package/dist/web/assets/use-app-theme-DEowpWRR.js +0 -1
- package/dist/web/assets/use-countdown-DlcwwJrs.js +0 -1
- package/dist/web/assets/use-router-link-CUoYaYUw.js +0 -1
- package/dist/web/assets/use-row-height-BsE9-rO2.js +0 -1
- package/dist/web/assets/use-server-events-C2X4Xz00.js +0 -1
- package/dist/web/assets/use-virtual-scroll-BAZGswHv.js +0 -1
- package/dist/web/assets/viewport-store-CCHiY2QG.js +0 -1
- package/dist/web/assets/weighted-lru-BGovtJ2a.js +0 -1
- package/dist/web/assets/workspace-navigation-DdW0rSGz.js +0 -1
- /package/dist/web/assets/{PanelResize-XjrbOj2S.css → AddToAgentButton-XjrbOj2S.css} +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { MAX_SEARCH_WORD_CODEPOINTS } from "../../shared/artifacts/constants.js";
|
|
2
|
+
import { searchCopy, searchTokens, searchGrams } from "../../shared/artifacts/search.js";
|
|
3
|
+
import { ArtifactSearchUnavailableError } from "../errors/artifacts.js";
|
|
4
|
+
export class ArtifactSearchRepository {
|
|
5
|
+
db;
|
|
6
|
+
statements = new Map();
|
|
7
|
+
storeId;
|
|
8
|
+
constructor(db, storeId) {
|
|
9
|
+
this.db = db;
|
|
10
|
+
this.storeId = storeId;
|
|
11
|
+
}
|
|
12
|
+
statement(sql) {
|
|
13
|
+
let prepared = this.statements.get(sql);
|
|
14
|
+
if (!prepared) {
|
|
15
|
+
prepared = this.db.prepare(sql);
|
|
16
|
+
this.statements.set(sql, prepared);
|
|
17
|
+
}
|
|
18
|
+
return prepared;
|
|
19
|
+
}
|
|
20
|
+
available() {
|
|
21
|
+
if (!this.statement("SELECT 1 FROM sqlite_master WHERE name='artifact_search_capabilities'").get()) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return Boolean(this.statement('SELECT available FROM artifact_search_capabilities WHERE id=1').get()?.available);
|
|
25
|
+
}
|
|
26
|
+
assertAvailable() {
|
|
27
|
+
if (!this.available())
|
|
28
|
+
throw new ArtifactSearchUnavailableError();
|
|
29
|
+
}
|
|
30
|
+
epoch() {
|
|
31
|
+
return (this.statement('SELECT COALESCE(SUM(epoch),0) epoch FROM artifact_search_epochs').get()?.epoch ?? 0);
|
|
32
|
+
}
|
|
33
|
+
changed() {
|
|
34
|
+
this.statement('INSERT INTO artifact_search_epochs VALUES(?,1) ON CONFLICT(store_id) DO UPDATE SET epoch=epoch+1').run(this.storeId);
|
|
35
|
+
}
|
|
36
|
+
pending() {
|
|
37
|
+
return this.statement(`SELECT c.artifact_id FROM artifact_current c LEFT JOIN artifact_search_documents d ON d.store_id=c.store_id AND d.artifact_id=c.artifact_id LEFT JOIN artifact_search_suppressed s ON s.store_id=c.store_id AND s.artifact_id=c.artifact_id WHERE c.store_id=? AND s.artifact_id IS NULL AND (d.version IS NULL OR d.version<>c.version) ORDER BY c.artifact_id`).all(this.storeId).map(row => row.artifact_id);
|
|
38
|
+
}
|
|
39
|
+
document(id) {
|
|
40
|
+
return this.statement('SELECT rowid,version,sha256,title,body,title_offsets,body_offsets FROM artifact_search_documents WHERE store_id=? AND artifact_id=?').get(this.storeId, id);
|
|
41
|
+
}
|
|
42
|
+
index(artifact, body) {
|
|
43
|
+
if (!this.available())
|
|
44
|
+
return;
|
|
45
|
+
if (this.statement('SELECT 1 FROM artifact_search_suppressed WHERE store_id=? AND artifact_id=?').get(this.storeId, artifact.id)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const old = this.document(artifact.id);
|
|
49
|
+
const title = searchCopy(artifact.title);
|
|
50
|
+
if (old &&
|
|
51
|
+
old.sha256 === artifact.sha256 &&
|
|
52
|
+
old.title === title.text &&
|
|
53
|
+
old.title_offsets === JSON.stringify(title.offsets)) {
|
|
54
|
+
this.statement('UPDATE artifact_search_documents SET version=? WHERE rowid=?').run(artifact.metadataVersion, old.rowid);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const normalizedBody = old && old.sha256 === artifact.sha256
|
|
58
|
+
? {
|
|
59
|
+
text: old.body,
|
|
60
|
+
offsets: JSON.parse(old.body_offsets)
|
|
61
|
+
}
|
|
62
|
+
: searchCopy(body());
|
|
63
|
+
this.removeDocument(artifact.id);
|
|
64
|
+
const inserted = this.statement('INSERT INTO artifact_search_documents(store_id,artifact_id,version,sha256,title,body,title_offsets,body_offsets) VALUES(?,?,?,?,?,?,?,?)').run(this.storeId, artifact.id, artifact.metadataVersion, artifact.sha256, title.text, normalizedBody.text, JSON.stringify(title.offsets), JSON.stringify(normalizedBody.offsets));
|
|
65
|
+
const rowid = Number(inserted.lastInsertRowid);
|
|
66
|
+
for (const table of ['artifact_search_fts', 'artifact_search_trigrams']) {
|
|
67
|
+
this.statement(`INSERT INTO ${table}(rowid,title,body) VALUES(?,?,?)`).run(rowid, title.text, normalizedBody.text);
|
|
68
|
+
}
|
|
69
|
+
for (const token of searchTokens(`${title.text}\n${normalizedBody.text}`)) {
|
|
70
|
+
const length = Array.from(token).length;
|
|
71
|
+
if (length > MAX_SEARCH_WORD_CODEPOINTS)
|
|
72
|
+
continue;
|
|
73
|
+
const frequency = this.statement('INSERT INTO artifact_search_words VALUES(?,?,?,1) ON CONFLICT(store_id,token) DO UPDATE SET frequency=frequency+1 RETURNING frequency').get(this.storeId, token, length);
|
|
74
|
+
const fresh = frequency?.frequency === 1;
|
|
75
|
+
this.statement('INSERT INTO artifact_search_document_words VALUES(?,?,?)').run(this.storeId, artifact.id, token);
|
|
76
|
+
if (fresh) {
|
|
77
|
+
for (const width of [1, 2]) {
|
|
78
|
+
for (const gram of searchGrams(token, width)) {
|
|
79
|
+
this.statement('INSERT INTO artifact_search_word_grams VALUES(?,?,?,?)').run(this.storeId, gram, width, token);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
this.changed();
|
|
85
|
+
}
|
|
86
|
+
removeDocument(id) {
|
|
87
|
+
const old = this.document(id);
|
|
88
|
+
if (!old)
|
|
89
|
+
return false;
|
|
90
|
+
for (const table of ['artifact_search_fts', 'artifact_search_trigrams']) {
|
|
91
|
+
this.statement(`DELETE FROM ${table} WHERE rowid=?`).run(old.rowid);
|
|
92
|
+
}
|
|
93
|
+
this.statement(`UPDATE artifact_search_words SET frequency=frequency-1 WHERE store_id=? AND token IN (SELECT token FROM artifact_search_document_words WHERE store_id=? AND artifact_id=?)`).run(this.storeId, this.storeId, id);
|
|
94
|
+
this.statement('DELETE FROM artifact_search_word_grams WHERE store_id=? AND token IN (SELECT token FROM artifact_search_words WHERE store_id=? AND frequency=0)').run(this.storeId, this.storeId);
|
|
95
|
+
this.statement('DELETE FROM artifact_search_words WHERE store_id=? AND frequency=0').run(this.storeId);
|
|
96
|
+
this.statement('DELETE FROM artifact_search_document_words WHERE store_id=? AND artifact_id=?').run(this.storeId, id);
|
|
97
|
+
this.statement('DELETE FROM artifact_search_documents WHERE rowid=?').run(old.rowid);
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
remove(id) {
|
|
101
|
+
if (this.removeDocument(id))
|
|
102
|
+
this.changed();
|
|
103
|
+
}
|
|
104
|
+
suppress(id, reason) {
|
|
105
|
+
this.removeDocument(id);
|
|
106
|
+
this.statement('INSERT INTO artifact_search_suppressed VALUES(?,?,?) ON CONFLICT(store_id,artifact_id) DO UPDATE SET reason=excluded.reason').run(this.storeId, id, reason);
|
|
107
|
+
this.changed();
|
|
108
|
+
}
|
|
109
|
+
reset() {
|
|
110
|
+
for (const row of this.statement('SELECT artifact_id FROM artifact_search_documents WHERE store_id=?').all(this.storeId)) {
|
|
111
|
+
this.removeDocument(row.artifact_id);
|
|
112
|
+
}
|
|
113
|
+
this.statement('DELETE FROM artifact_search_suppressed WHERE store_id=?').run(this.storeId);
|
|
114
|
+
this.changed();
|
|
115
|
+
}
|
|
116
|
+
candidates(token, edits, limit) {
|
|
117
|
+
const width = Array.from(token).length >= 8 ? 2 : 1;
|
|
118
|
+
return this.statement(`SELECT w.token,w.frequency,COUNT(*) overlap FROM artifact_search_word_grams g JOIN artifact_search_words w ON w.store_id=g.store_id AND w.token=g.token WHERE g.store_id=? AND g.width=? AND g.gram IN (SELECT value FROM json_each(?)) AND w.length BETWEEN ? AND ? GROUP BY w.token ORDER BY overlap DESC,w.frequency DESC,w.token LIMIT ?`).all(this.storeId, width, JSON.stringify(searchGrams(token, width)), Array.from(token).length - edits, Array.from(token).length + edits, limit);
|
|
119
|
+
}
|
|
120
|
+
select(input, normalized, exactExpression, fuzzyExpression, offset, limit) {
|
|
121
|
+
const params = [];
|
|
122
|
+
const hits = [];
|
|
123
|
+
if (normalized) {
|
|
124
|
+
if (Array.from(normalized).length >= 3) {
|
|
125
|
+
hits.push('SELECT rowid,bm25(artifact_search_trigrams,5,1) score,0 tier FROM artifact_search_trigrams WHERE artifact_search_trigrams MATCH ?');
|
|
126
|
+
params.push('"' + normalized.replaceAll('"', '""') + '"');
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
hits.push("SELECT rowid,0 score,0 tier FROM artifact_search_documents WHERE store_id=? AND (title LIKE ? ESCAPE '\\' OR body LIKE ? ESCAPE '\\')");
|
|
130
|
+
const literal = '%' + normalized.replace(/[\\%_]/g, '\\$&') + '%';
|
|
131
|
+
params.push(this.storeId, literal, literal);
|
|
132
|
+
}
|
|
133
|
+
if (exactExpression) {
|
|
134
|
+
hits.push('SELECT rowid,bm25(artifact_search_fts,5,1) score,1 tier FROM artifact_search_fts WHERE artifact_search_fts MATCH ?');
|
|
135
|
+
params.push(exactExpression);
|
|
136
|
+
}
|
|
137
|
+
if (fuzzyExpression) {
|
|
138
|
+
hits.push('SELECT rowid,bm25(artifact_search_fts,5,1) score,2 tier FROM artifact_search_fts WHERE artifact_search_fts MATCH ?');
|
|
139
|
+
params.push(fuzzyExpression);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
hits.push('SELECT rowid,0 score,0 tier FROM artifact_search_documents');
|
|
144
|
+
}
|
|
145
|
+
const filters = input.filters ?? {};
|
|
146
|
+
const where = [
|
|
147
|
+
'd.store_id=?',
|
|
148
|
+
"json_extract(c.snapshot_json,'$.status') IN (SELECT value FROM json_each(?))"
|
|
149
|
+
];
|
|
150
|
+
params.push(this.storeId, JSON.stringify(filters.statuses ?? ['accepted']));
|
|
151
|
+
if (filters.typeIds) {
|
|
152
|
+
where.push("json_extract(c.snapshot_json,'$.typeId') IN (SELECT value FROM json_each(?))");
|
|
153
|
+
params.push(JSON.stringify(filters.typeIds));
|
|
154
|
+
}
|
|
155
|
+
if (filters.taskIds) {
|
|
156
|
+
where.push("EXISTS(SELECT 1 FROM json_each(c.snapshot_json,'$.taskIds') WHERE value IN (SELECT value FROM json_each(?)))");
|
|
157
|
+
params.push(JSON.stringify(filters.taskIds));
|
|
158
|
+
}
|
|
159
|
+
if (filters.tags) {
|
|
160
|
+
where.push(filters.tagMode === 'any'
|
|
161
|
+
? "EXISTS(SELECT 1 FROM json_each(c.snapshot_json,'$.tags') WHERE value IN (SELECT value FROM json_each(?)))"
|
|
162
|
+
: "NOT EXISTS(SELECT 1 FROM json_each(?) f WHERE f.value NOT IN (SELECT value FROM json_each(c.snapshot_json,'$.tags')))");
|
|
163
|
+
params.push(JSON.stringify(filters.tags));
|
|
164
|
+
}
|
|
165
|
+
// Stored timestamps are UTC ISO strings, so text comparison keeps time order.
|
|
166
|
+
if (filters.createdFrom) {
|
|
167
|
+
where.push("json_extract(c.snapshot_json,'$.createdAt') >= ?");
|
|
168
|
+
params.push(new Date(filters.createdFrom).toISOString());
|
|
169
|
+
}
|
|
170
|
+
if (filters.createdTo) {
|
|
171
|
+
where.push("json_extract(c.snapshot_json,'$.createdAt') <= ?");
|
|
172
|
+
params.push(new Date(filters.createdTo).toISOString());
|
|
173
|
+
}
|
|
174
|
+
const sort = input.sort === 'createdAt'
|
|
175
|
+
? "json_extract(c.snapshot_json,'$.createdAt') DESC"
|
|
176
|
+
: input.sort === 'metadataUpdatedAt'
|
|
177
|
+
? "json_extract(c.snapshot_json,'$.metadataUpdatedAt') DESC"
|
|
178
|
+
: 'h.tier,h.score';
|
|
179
|
+
params.push(limit, offset);
|
|
180
|
+
return this.statement(`WITH hits AS MATERIALIZED (${hits.join(' UNION ALL ')}), ranked AS (SELECT rowid,tier,score FROM (SELECT rowid,tier,score,ROW_NUMBER() OVER (PARTITION BY rowid ORDER BY tier,score) n FROM hits) WHERE n=1) SELECT d.artifact_id id,c.snapshot_json,h.tier,h.score FROM ranked h JOIN artifact_search_documents d ON d.rowid=h.rowid JOIN artifact_current c ON c.store_id=d.store_id AND c.artifact_id=d.artifact_id WHERE ${where.join(' AND ')} ORDER BY ${sort},d.artifact_id LIMIT ? OFFSET ?`).all(...params);
|
|
181
|
+
}
|
|
182
|
+
diagnostics() {
|
|
183
|
+
const available = this.available();
|
|
184
|
+
if (!available)
|
|
185
|
+
return { available, documents: 0, suppressed: [] };
|
|
186
|
+
return {
|
|
187
|
+
available,
|
|
188
|
+
documents: this.statement('SELECT COUNT(*) count FROM artifact_search_documents WHERE store_id=?').get(this.storeId).count,
|
|
189
|
+
suppressed: this.statement('SELECT artifact_id id,reason FROM artifact_search_suppressed WHERE store_id=? ORDER BY artifact_id').all(this.storeId)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ArtifactNotFoundError } from "../errors/artifacts.js";
|
|
2
|
+
export class ArtifactTransitionRepository {
|
|
3
|
+
db;
|
|
4
|
+
storeId;
|
|
5
|
+
constructor(db, storeId) {
|
|
6
|
+
this.db = db;
|
|
7
|
+
this.storeId = storeId;
|
|
8
|
+
}
|
|
9
|
+
operation(id) {
|
|
10
|
+
const row = this.db
|
|
11
|
+
.prepare('SELECT payload_json FROM artifact_transition_current WHERE store_id=? AND id=?')
|
|
12
|
+
.get(this.storeId, id);
|
|
13
|
+
if (!row) {
|
|
14
|
+
throw new ArtifactNotFoundError();
|
|
15
|
+
}
|
|
16
|
+
return JSON.parse(row.payload_json);
|
|
17
|
+
}
|
|
18
|
+
forArtifact(artifactId, limit = 10) {
|
|
19
|
+
const rows = this.db
|
|
20
|
+
.prepare('SELECT payload_json FROM artifact_transition_current WHERE store_id=? AND artifact_id=?')
|
|
21
|
+
.all(this.storeId, artifactId);
|
|
22
|
+
return rows
|
|
23
|
+
.map(row => JSON.parse(row.payload_json))
|
|
24
|
+
.sort((a, b) => b.createdAt - a.createdAt)
|
|
25
|
+
.slice(0, limit);
|
|
26
|
+
}
|
|
27
|
+
unfinished() {
|
|
28
|
+
const rows = this.db
|
|
29
|
+
.prepare(`SELECT payload_json FROM artifact_transition_current WHERE store_id=?
|
|
30
|
+
AND json_extract(payload_json,'$.stage') IN ('preparing','validating','applying')`)
|
|
31
|
+
.all(this.storeId);
|
|
32
|
+
return rows.map(row => JSON.parse(row.payload_json));
|
|
33
|
+
}
|
|
34
|
+
append(value) {
|
|
35
|
+
const payload = JSON.stringify(value);
|
|
36
|
+
this.db
|
|
37
|
+
.prepare('INSERT INTO artifact_transition_events(store_id,id,payload_json) VALUES(?,?,?)')
|
|
38
|
+
.run(this.storeId, value.id, payload);
|
|
39
|
+
this.db
|
|
40
|
+
.prepare(`INSERT INTO artifact_transition_current VALUES(?,?,?,?)
|
|
41
|
+
ON CONFLICT(store_id,id) DO UPDATE SET payload_json=excluded.payload_json`)
|
|
42
|
+
.run(this.storeId, value.id, value.artifactId, payload);
|
|
43
|
+
}
|
|
44
|
+
history(id) {
|
|
45
|
+
const rows = this.db
|
|
46
|
+
.prepare('SELECT payload_json FROM artifact_transition_events WHERE store_id=? AND id=? ORDER BY seq')
|
|
47
|
+
.all(this.storeId, id);
|
|
48
|
+
return rows.map(row => JSON.parse(row.payload_json));
|
|
49
|
+
}
|
|
50
|
+
rebuild() {
|
|
51
|
+
this.db
|
|
52
|
+
.prepare('DELETE FROM artifact_transition_current WHERE store_id=?')
|
|
53
|
+
.run(this.storeId);
|
|
54
|
+
this.db
|
|
55
|
+
.prepare(`INSERT INTO artifact_transition_current
|
|
56
|
+
SELECT store_id,id,json_extract(payload_json,'$.artifactId'),payload_json
|
|
57
|
+
FROM artifact_transition_events e WHERE store_id=? AND seq=(
|
|
58
|
+
SELECT MAX(seq) FROM artifact_transition_events n WHERE n.store_id=e.store_id AND n.id=e.id)`)
|
|
59
|
+
.run(this.storeId);
|
|
60
|
+
}
|
|
61
|
+
request(requestId) {
|
|
62
|
+
const row = this.db
|
|
63
|
+
.prepare('SELECT payload_hash,operation_id FROM artifact_transition_requests WHERE store_id=? AND request_id=?')
|
|
64
|
+
.get(this.storeId, requestId);
|
|
65
|
+
return row
|
|
66
|
+
? { payloadHash: row.payload_hash, operationId: row.operation_id }
|
|
67
|
+
: undefined;
|
|
68
|
+
}
|
|
69
|
+
appendRequest(requestId, payloadHash, operationId) {
|
|
70
|
+
this.db
|
|
71
|
+
.prepare('INSERT INTO artifact_transition_requests(store_id,request_id,payload_hash,operation_id) VALUES(?,?,?,?)')
|
|
72
|
+
.run(this.storeId, requestId, payloadHash, operationId);
|
|
73
|
+
}
|
|
74
|
+
consent(operationId) {
|
|
75
|
+
const row = this.db
|
|
76
|
+
.prepare('SELECT payload_json FROM artifact_transition_consents WHERE store_id=? AND operation_id=?')
|
|
77
|
+
.get(this.storeId, operationId);
|
|
78
|
+
return row ? JSON.parse(row.payload_json) : undefined;
|
|
79
|
+
}
|
|
80
|
+
appendConsent(value) {
|
|
81
|
+
this.db
|
|
82
|
+
.prepare('INSERT INTO artifact_transition_consents(store_id,operation_id,payload_json) VALUES(?,?,?)')
|
|
83
|
+
.run(this.storeId, value.operationId, JSON.stringify(value));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { artifactLeaseBusyError, ArtifactNotFoundError } from "../errors/artifacts.js";
|
|
2
|
+
export class ArtifactValidationRepository {
|
|
3
|
+
db;
|
|
4
|
+
storeId;
|
|
5
|
+
constructor(db, storeId) {
|
|
6
|
+
this.db = db;
|
|
7
|
+
this.storeId = storeId;
|
|
8
|
+
}
|
|
9
|
+
proposal(id) {
|
|
10
|
+
const row = this.db
|
|
11
|
+
.prepare('SELECT payload_json FROM artifact_change_set_events WHERE store_id=? AND id=? ORDER BY version DESC LIMIT 1')
|
|
12
|
+
.get(this.storeId, id);
|
|
13
|
+
if (!row)
|
|
14
|
+
throw new ArtifactNotFoundError();
|
|
15
|
+
return JSON.parse(row.payload_json);
|
|
16
|
+
}
|
|
17
|
+
proposalVersion(id, version) {
|
|
18
|
+
const row = this.db
|
|
19
|
+
.prepare('SELECT payload_json FROM artifact_change_set_events WHERE store_id=? AND id=? AND version=?')
|
|
20
|
+
.get(this.storeId, id, version);
|
|
21
|
+
if (!row)
|
|
22
|
+
throw new ArtifactNotFoundError();
|
|
23
|
+
return JSON.parse(row.payload_json);
|
|
24
|
+
}
|
|
25
|
+
proposalRequest(requestId) {
|
|
26
|
+
const row = this.db
|
|
27
|
+
.prepare('SELECT payload_json FROM artifact_change_set_events WHERE store_id=? AND request_id=?')
|
|
28
|
+
.get(this.storeId, requestId);
|
|
29
|
+
return row ? JSON.parse(row.payload_json) : undefined;
|
|
30
|
+
}
|
|
31
|
+
appendProposal(value) {
|
|
32
|
+
this.db
|
|
33
|
+
.prepare('INSERT INTO artifact_change_set_events(store_id,id,version,request_id,payload_json) VALUES(?,?,?,?,?)')
|
|
34
|
+
.run(this.storeId, value.id, value.version, value.requestId, JSON.stringify(value));
|
|
35
|
+
}
|
|
36
|
+
validation(id) {
|
|
37
|
+
const row = this.db
|
|
38
|
+
.prepare('SELECT payload_json FROM artifact_validation_current WHERE store_id=? AND id=?')
|
|
39
|
+
.get(this.storeId, id);
|
|
40
|
+
if (!row)
|
|
41
|
+
throw new ArtifactNotFoundError();
|
|
42
|
+
return JSON.parse(row.payload_json);
|
|
43
|
+
}
|
|
44
|
+
appendValidation(value, eventKind = ['pass', 'conflict'].includes(value.state)
|
|
45
|
+
? 'completed'
|
|
46
|
+
: value.state) {
|
|
47
|
+
const payload = JSON.stringify({ ...value, eventKind });
|
|
48
|
+
this.db
|
|
49
|
+
.prepare('INSERT INTO artifact_validation_events(store_id,id,payload_json) VALUES(?,?,?)')
|
|
50
|
+
.run(this.storeId, value.id, payload);
|
|
51
|
+
this.db
|
|
52
|
+
.prepare('INSERT INTO artifact_validation_current VALUES(?,?,?) ON CONFLICT(store_id,id) DO UPDATE SET payload_json=excluded.payload_json')
|
|
53
|
+
.run(this.storeId, value.id, payload);
|
|
54
|
+
}
|
|
55
|
+
history(id, afterSeq = 0, limit = 50) {
|
|
56
|
+
return this.db
|
|
57
|
+
.prepare('SELECT seq,payload_json FROM artifact_validation_events WHERE store_id=? AND id=? AND seq>? ORDER BY seq LIMIT ?')
|
|
58
|
+
.all(this.storeId, id, afterSeq, limit).map(row => ({
|
|
59
|
+
seq: row.seq,
|
|
60
|
+
validation: JSON.parse(row.payload_json)
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
rebuild() {
|
|
64
|
+
this.db
|
|
65
|
+
.prepare('DELETE FROM artifact_validation_current WHERE store_id=?')
|
|
66
|
+
.run(this.storeId);
|
|
67
|
+
this.db
|
|
68
|
+
.prepare(`INSERT INTO artifact_validation_current SELECT store_id,id,payload_json FROM artifact_validation_events e WHERE store_id=? AND seq=(SELECT MAX(seq) FROM artifact_validation_events n WHERE n.store_id=e.store_id AND n.id=e.id)`)
|
|
69
|
+
.run(this.storeId);
|
|
70
|
+
}
|
|
71
|
+
lease() {
|
|
72
|
+
return this.db
|
|
73
|
+
.prepare('SELECT validation_id,owner,owner_pid,expires_at FROM artifact_validation_leases WHERE store_id=?')
|
|
74
|
+
.get(this.storeId);
|
|
75
|
+
}
|
|
76
|
+
claim(id, owner, now, ttl) {
|
|
77
|
+
if (this.lease()) {
|
|
78
|
+
throw artifactLeaseBusyError('Another validation job is active.');
|
|
79
|
+
}
|
|
80
|
+
this.db
|
|
81
|
+
.prepare('INSERT INTO artifact_validation_leases VALUES(?,?,?,?,?)')
|
|
82
|
+
.run(this.storeId, id, owner, process.pid, now + ttl);
|
|
83
|
+
}
|
|
84
|
+
release(id, owner) {
|
|
85
|
+
this.db
|
|
86
|
+
.prepare('DELETE FROM artifact_validation_leases WHERE store_id=? AND validation_id=? AND owner=?')
|
|
87
|
+
.run(this.storeId, id, owner);
|
|
88
|
+
}
|
|
89
|
+
/** Records that `owner` is alive; old rows of dead owners are dropped. */
|
|
90
|
+
beat(owner, now, keepMs) {
|
|
91
|
+
this.db
|
|
92
|
+
.prepare(`INSERT INTO artifact_owner_heartbeats VALUES(?,?,?)
|
|
93
|
+
ON CONFLICT(store_id,owner) DO UPDATE SET beat_at=excluded.beat_at`)
|
|
94
|
+
.run(this.storeId, owner, now);
|
|
95
|
+
this.db
|
|
96
|
+
.prepare('DELETE FROM artifact_owner_heartbeats WHERE store_id=? AND beat_at<?')
|
|
97
|
+
.run(this.storeId, now - keepMs);
|
|
98
|
+
}
|
|
99
|
+
forget(owner) {
|
|
100
|
+
this.db
|
|
101
|
+
.prepare('DELETE FROM artifact_owner_heartbeats WHERE store_id=? AND owner=?')
|
|
102
|
+
.run(this.storeId, owner);
|
|
103
|
+
}
|
|
104
|
+
/** Time of the last heartbeat, or undefined when the owner never wrote one. */
|
|
105
|
+
heartbeat(owner) {
|
|
106
|
+
const row = this.db
|
|
107
|
+
.prepare('SELECT beat_at FROM artifact_owner_heartbeats WHERE store_id=? AND owner=?')
|
|
108
|
+
.get(this.storeId, owner);
|
|
109
|
+
return row?.beat_at;
|
|
110
|
+
}
|
|
111
|
+
appendAuthorization(id, data) {
|
|
112
|
+
this.db
|
|
113
|
+
.prepare('INSERT INTO artifact_user_authorizations(store_id,id,payload_json) VALUES(?,?,?)')
|
|
114
|
+
.run(this.storeId, id, JSON.stringify(data));
|
|
115
|
+
}
|
|
116
|
+
authorizationEvent(id, kind, data) {
|
|
117
|
+
this.db
|
|
118
|
+
.prepare('INSERT INTO artifact_authorization_events(store_id,id,kind,payload_json) VALUES(?,?,?,?)')
|
|
119
|
+
.run(this.storeId, id, kind, JSON.stringify(data));
|
|
120
|
+
}
|
|
121
|
+
consumed(id) {
|
|
122
|
+
return Boolean(this.db
|
|
123
|
+
.prepare("SELECT 1 FROM artifact_authorization_events WHERE store_id=? AND id=? AND kind='consumed'")
|
|
124
|
+
.get(this.storeId, id));
|
|
125
|
+
}
|
|
126
|
+
commitRequest(requestId) {
|
|
127
|
+
const row = this.db
|
|
128
|
+
.prepare('SELECT seq,payload_hash,result_json FROM artifact_lifecycle_commits WHERE store_id=? AND request_id=?')
|
|
129
|
+
.get(this.storeId, requestId);
|
|
130
|
+
return row
|
|
131
|
+
? {
|
|
132
|
+
payloadHash: row.payload_hash,
|
|
133
|
+
result: {
|
|
134
|
+
...JSON.parse(row.result_json),
|
|
135
|
+
eventSeq: row.seq
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
: undefined;
|
|
139
|
+
}
|
|
140
|
+
appendCommit(requestId, payloadHash, result) {
|
|
141
|
+
const inserted = this.db
|
|
142
|
+
.prepare('INSERT INTO artifact_lifecycle_commits(store_id,request_id,payload_hash,result_json) VALUES(?,?,?,?)')
|
|
143
|
+
.run(this.storeId, requestId, payloadHash, JSON.stringify(result));
|
|
144
|
+
return Number(inserted.lastInsertRowid);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withSavepoint } from "../db/transaction.js";
|
|
1
2
|
import { randomUUID } from 'node:crypto';
|
|
2
3
|
function toNote(row) {
|
|
3
4
|
return {
|
|
@@ -25,16 +26,7 @@ export class NotesCatalogRepository {
|
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
transaction(run) {
|
|
28
|
-
this.db
|
|
29
|
-
try {
|
|
30
|
-
const value = run();
|
|
31
|
-
this.db.exec('RELEASE notes_catalog');
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
catch (error) {
|
|
35
|
-
this.db.exec('ROLLBACK TO notes_catalog; RELEASE notes_catalog');
|
|
36
|
-
throw error;
|
|
37
|
-
}
|
|
29
|
+
return withSavepoint(this.db, run);
|
|
38
30
|
}
|
|
39
31
|
all() {
|
|
40
32
|
return this.db
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ArtifactConflictError } from "../errors/artifacts.js";
|
|
2
|
+
export class TaskRepository {
|
|
3
|
+
db;
|
|
4
|
+
storeId;
|
|
5
|
+
constructor(db, storeId) {
|
|
6
|
+
this.db = db;
|
|
7
|
+
this.storeId = storeId;
|
|
8
|
+
}
|
|
9
|
+
// oxlint-disable-next-line typescript/no-unnecessary-type-parameters -- The caller supplies the domain type for stored JSON.
|
|
10
|
+
get(kind, id) {
|
|
11
|
+
const row = this.db
|
|
12
|
+
.prepare(`SELECT snapshot_json FROM ${kind}_current WHERE store_id=? AND id=?`)
|
|
13
|
+
.get(this.storeId, id);
|
|
14
|
+
return row ? JSON.parse(row.snapshot_json) : undefined;
|
|
15
|
+
}
|
|
16
|
+
all(kind) {
|
|
17
|
+
return this.db
|
|
18
|
+
.prepare(`SELECT snapshot_json FROM ${kind}_current WHERE store_id=? ORDER BY id`)
|
|
19
|
+
.all(this.storeId).map(row => JSON.parse(row.snapshot_json));
|
|
20
|
+
}
|
|
21
|
+
history(kind, id) {
|
|
22
|
+
return this.db
|
|
23
|
+
.prepare(`SELECT * FROM ${kind}_versions WHERE store_id=? AND id=? ORDER BY version`)
|
|
24
|
+
.all(this.storeId, id).map(row => ({
|
|
25
|
+
snapshot: JSON.parse(row.snapshot_json),
|
|
26
|
+
requestId: row.request_id,
|
|
27
|
+
actor: JSON.parse(row.actor_json),
|
|
28
|
+
createdAt: row.created_at
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
append(kind, snapshot, requestId, actor, now) {
|
|
32
|
+
this.db
|
|
33
|
+
.prepare(`INSERT INTO ${kind}_versions VALUES(?,?,?,?,?,?,?)`)
|
|
34
|
+
.run(this.storeId, snapshot.id, snapshot.version, requestId, JSON.stringify(snapshot), JSON.stringify(actor), now);
|
|
35
|
+
this.db
|
|
36
|
+
.prepare(`INSERT INTO ${kind}_current VALUES(?,?,?) ON CONFLICT(store_id,id) DO UPDATE SET snapshot_json=excluded.snapshot_json`)
|
|
37
|
+
.run(this.storeId, snapshot.id, JSON.stringify(snapshot));
|
|
38
|
+
}
|
|
39
|
+
// oxlint-disable-next-line typescript/no-unnecessary-type-parameters -- The command owner knows the stored result type.
|
|
40
|
+
replay(requestId, hash) {
|
|
41
|
+
if (this.db
|
|
42
|
+
.prepare('SELECT 1 FROM artifact_operations WHERE store_id=? AND request_id=?')
|
|
43
|
+
.get(this.storeId, requestId)) {
|
|
44
|
+
throw new ArtifactConflictError('Request identifier already used for an artifact operation.');
|
|
45
|
+
}
|
|
46
|
+
const row = this.db
|
|
47
|
+
.prepare('SELECT payload_hash,result_json FROM artifact_definition_operations WHERE store_id=? AND request_id=?')
|
|
48
|
+
.get(this.storeId, requestId);
|
|
49
|
+
if (!row) {
|
|
50
|
+
const reserved = this.db
|
|
51
|
+
.prepare('SELECT 1 FROM artifact_type_versions WHERE store_id=? AND request_id=?')
|
|
52
|
+
.get(this.storeId, requestId);
|
|
53
|
+
if (reserved) {
|
|
54
|
+
throw new ArtifactConflictError('Request identifier belongs to type initialization.');
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
if (row.payload_hash !== hash) {
|
|
59
|
+
throw new ArtifactConflictError('Request identifier already used for a different operation.');
|
|
60
|
+
}
|
|
61
|
+
return { result: JSON.parse(row.result_json) };
|
|
62
|
+
}
|
|
63
|
+
record(requestId, hash, result) {
|
|
64
|
+
this.db
|
|
65
|
+
.prepare('INSERT INTO artifact_definition_operations VALUES(?,?,?,?)')
|
|
66
|
+
.run(this.storeId, requestId, hash, JSON.stringify(result));
|
|
67
|
+
}
|
|
68
|
+
assertArtifactRequest(requestId) {
|
|
69
|
+
if (this.db
|
|
70
|
+
.prepare('SELECT 1 FROM artifact_definition_operations WHERE store_id=? AND request_id=?')
|
|
71
|
+
.get(this.storeId, requestId)) {
|
|
72
|
+
throw new ArtifactConflictError('Request identifier already used for a definition operation.');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
assignment(sessionId) {
|
|
76
|
+
const row = this.db
|
|
77
|
+
.prepare('SELECT version,task_ids_json FROM task_chat_link_events WHERE store_id=? AND session_id=? ORDER BY version DESC LIMIT 1')
|
|
78
|
+
.get(this.storeId, sessionId);
|
|
79
|
+
return {
|
|
80
|
+
sessionId,
|
|
81
|
+
version: row?.version ?? 0,
|
|
82
|
+
taskIds: row ? JSON.parse(row.task_ids_json) : []
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
appendAssignment(sessionId, version, taskIds, title, requestId, actor, now) {
|
|
86
|
+
this.db
|
|
87
|
+
.prepare('INSERT INTO task_chat_link_events(store_id,session_id,version,request_id,task_ids_json,chat_title_snapshot,actor_json,created_at) VALUES(?,?,?,?,?,?,?,?)')
|
|
88
|
+
.run(this.storeId, sessionId, version, requestId, JSON.stringify(taskIds), title, JSON.stringify(actor), now);
|
|
89
|
+
}
|
|
90
|
+
chatHistory() {
|
|
91
|
+
return this.db
|
|
92
|
+
.prepare('SELECT * FROM task_chat_link_events WHERE store_id=? ORDER BY seq')
|
|
93
|
+
.all(this.storeId).map(row => ({
|
|
94
|
+
seq: row.seq,
|
|
95
|
+
sessionId: row.session_id,
|
|
96
|
+
version: row.version,
|
|
97
|
+
taskIds: JSON.parse(row.task_ids_json),
|
|
98
|
+
title: row.chat_title_snapshot,
|
|
99
|
+
actor: JSON.parse(row.actor_json),
|
|
100
|
+
createdAt: row.created_at,
|
|
101
|
+
requestId: row.request_id
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
rebuild() {
|
|
105
|
+
for (const kind of ['task', 'artifact_type']) {
|
|
106
|
+
this.db
|
|
107
|
+
.prepare(`DELETE FROM ${kind}_current WHERE store_id=?`)
|
|
108
|
+
.run(this.storeId);
|
|
109
|
+
this.db
|
|
110
|
+
.prepare(`INSERT INTO ${kind}_current SELECT v.store_id,v.id,v.snapshot_json FROM ${kind}_versions v WHERE v.store_id=? AND v.version=(SELECT MAX(n.version) FROM ${kind}_versions n WHERE n.store_id=v.store_id AND n.id=v.id)`)
|
|
111
|
+
.run(this.storeId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -72,7 +72,10 @@ export async function agentRoutes(app, opts) {
|
|
|
72
72
|
throw new NotFoundError(`Review ${reviewId} not found`);
|
|
73
73
|
}
|
|
74
74
|
// The agent starts in the background; failure shows up as a closed session.
|
|
75
|
-
const
|
|
75
|
+
const deviceId = request.access?.device.status === 'device'
|
|
76
|
+
? request.access.device.device.id
|
|
77
|
+
: undefined;
|
|
78
|
+
const session = registry.create(presetId, reviewId ?? null, name, deviceId);
|
|
76
79
|
reply.code(201);
|
|
77
80
|
return session.info();
|
|
78
81
|
});
|
|
@@ -125,6 +128,7 @@ export async function agentRoutes(app, opts) {
|
|
|
125
128
|
session.assertCanPrompt();
|
|
126
129
|
const blocks = await buildPromptBlocks(request.body, {
|
|
127
130
|
notes: opts.notes,
|
|
131
|
+
artifacts: opts.artifacts,
|
|
128
132
|
db,
|
|
129
133
|
repositoryPath,
|
|
130
134
|
embeddedContext: session.supportsEmbeddedContext,
|
|
@@ -250,6 +254,9 @@ export async function agentRoutes(app, opts) {
|
|
|
250
254
|
data: message.envelope
|
|
251
255
|
});
|
|
252
256
|
}
|
|
257
|
+
else if (message.type === 'artifact-actions') {
|
|
258
|
+
safeSend(reply.sse, { event: 'artifact-actions', data: {} });
|
|
259
|
+
}
|
|
253
260
|
else if (message.type === 'gap') {
|
|
254
261
|
safeSend(reply.sse, {
|
|
255
262
|
event: 'gap',
|