chainlesschain 0.162.161 → 0.162.162

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 (178) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-DMn528q-.js → AIOps-ClI2ALgv.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-D9ZcDCJL.js → ActionButton-BDjRcJaK.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-A_K-8PX0.js → Analytics-DikSRsaT.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-D4pFW3X6.js → AppLayout-9mLhMFmz.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-Dz46COAd.js → Artifacts-BSr88BrH.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-cbMjbyg0.js → Audit-CdvyimOF.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-Dtf88GAj.js → BackgroundAgents-D3_hCedh.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-C5KRxn52.js → Backup-Cyvv9RHf.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-Dd2UK3BN.js → BaseInput-BZM14kt8.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-lptKTFdG.js → Chat-DrQSokVz.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-C2KLtwHz.js → ChatBubbleRenderer-HwJR-C6B.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-_yspG6rG.js → Checkbox-bFLYeWMV.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-BGq_GAha.js → Codegen-7mN7xJXT.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-CePor71g.js → Col-DAB5ZWm7.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-CLOWhIT7.js → Community-B_1TymaK.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-CivJt2vT.js → Compact-Bq1uSWLJ.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-Btmo1GGE.js → Compliance-CyiE1jEe.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-Ct35OlG4.js → Cowork-Cpk0D7vm.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-CTc2GmhB.js → Cron-d_Lv3rdB.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-ZtiBETk1.js → Crosschain-DMqhHjMR.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-BNqMQQXw.js → DID-Br-oPuBw.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-BmzZd-9V.js → Dashboard-CfLW_RaP.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-CMVgvP2M.js → Dropdown-DZnTOExV.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-CcqQFAfT.js → EmailListRenderer-DHIUHDv1.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CTqB1_4V.js → FamilyGuardDashboard-Bw3t3myu.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-CiKOOzlb.js → Federation-D9cpQPAY.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-Wk-OT0gr.js → FormItemContext-Jdczr9Mr.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-DbEQT6ue.js → GenericCardRenderer-BT8ZMpC5.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-0ZvCPSD9.js → Git-DjARip2b.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CmVuKkPb.js → Governance-BgWbSRcj.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-CTWE3Jwg.js → Inference-CfouJciM.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-CBEIF00L.js → KnowledgeGraph-50l7mrAr.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-DLhxDwVG.js → Logs-rq50H84B.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-DUPIEdQH.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-BgsCBrnc.js → Marketplace-BYgPDmHU.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-ClBUGDS2.js → McpTools-5DVgcFdx.js} +3 -3
  38. package/src/assets/web-panel/assets/{Memory-CnG_ZnYw.js → Memory-B70LPk7f.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BUOAbR1Z.js → MobileBridge-De8ssA5Y.js} +1 -1
  40. package/src/assets/web-panel/assets/MobileProjects-D10VISps.js +1 -0
  41. package/src/assets/web-panel/assets/{Mtc-CLjt4kCD.js → Mtc-RJsOTsIA.js} +2 -2
  42. package/src/assets/web-panel/assets/{MtcAudit-f24U9Aes.js → MtcAudit-Crh-6BEK.js} +5 -5
  43. package/src/assets/web-panel/assets/{Multisig-GrmGQbSq.js → Multisig-wuoR5l3x.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-DADaWn-n.js → NLProgramming-U2Mji4fZ.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-xtf5RX6C.js → Notes-CdTZAyDH.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-Cd27Rgtx.js → NotificationSettings-C-FucWE7.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-fXRxlDjl.js → OrderTableRenderer-DCYFTeaI.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-joCFlNB0.js → Organization-an3OF85L.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-B1HoURq0.js → Overflow-C-1vmYFe.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-DiwsKbT7.js → P2P-Cwh47xKg.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-Xe-BsW6S.js → PdhVaultBrowser-Dm38GT0k.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-C23qi8kl.js → Permissions-DS2Y8awD.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-BS1syX2f.js → PersonalDataHub-BQNziA0I.js} +3 -3
  54. package/src/assets/web-panel/assets/{Pipeline-DRYwwDyh.js → Pipeline-DF85L1ue.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-BQKaDHPH.js → Privacy-BuLornF-.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-BC6F9xiG.js → ProjectInit-C3Y31IwX.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-ClFPc1Nd.js → ProjectSettings-BCPiI8aD.js} +2 -2
  58. package/src/assets/web-panel/assets/Projects-BZ6s4k6g.js +1 -0
  59. package/src/assets/web-panel/assets/{Providers-CLWuOUNt.js → Providers-D3Wp022X.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-DiqULTxb.js → QrScannerModal-CUJfQkH4.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-9A03P-E_.js → QuickAsk-UAc0EO8l.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-CJZAnbq_.js → Recommend-BaxKupcs.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C9A1R77h.js → RemoteSession-C75NNnXZ.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-BIZc6Rky.js → Reputation-BVXynZAk.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-DfIPNtuG.js → Row-C5MRZ0bi.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-C5znFcQ1.js → RssFeed-DAKkEYka.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-DSs2z3OX.js → Search-DvWv9YOA.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-CV6LcrLY.js → Security-B5peafW1.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-cmhoX0Xj.js → Services-UQmvPEaG.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-tCsg2po7.js → Skeleton-C3bhWpuF.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-BK1KUDiy.js → Skills-DfkKf9_H.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-yRgyeA82.js → Sla-DqMSjlBM.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-c1mo1mlp.js → SpeechSettings-C-WbxWUX.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-koIAfuT3.js → SyncSettings-CYuHZ4N2.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-DkkreAaB.js → Tasks-CyeAyB9d.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-fy5Ctf9M.js → Templates-BTCeQnpq.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-Bw70Jf6S.js → Tenant-BifQuA9Y.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-BKh6Rx-4.js → Terminal-Bx_9Bocf.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-Dg54WP0c.js → TimelineRenderer-BX0RFCOm.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-BvvD5SxJ.js → Tokens-CGHrCmUS.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-B7Ug9x4e.js → Trigger-DlqaY4SO.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-BjvuMORY.js → Trust-DfOmj-ay.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-CZqhkx8p.js → UkeySign-B72jH5fE.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-ClR50lhX.js → VideoEditing-BT-63fqv.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-DlfppYjx.js → Wallet-Dsul3sHr.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-BirgVr8B.js → WebAuthn-Izkwwdgy.js} +2 -2
  87. package/src/assets/web-panel/assets/{WorkflowEditor-B8DP_bax.js → WorkflowEditor-D3FHSiH1.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-DA8AUZzL.js → chat-CmVz5z3U.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-C38pLGp1.js → colors-CuLgyJBp.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-81rtr98o.js → compact-item-Ml1YkXpw.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-D34ixq8t.js → createContext-BvjJ48bs.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-DhiGrbsh.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-D4bzqTrZ.js → hasIn-DVC0157C.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-D_2VYPr1.js → index-4SBta3d7.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CoVgZw_b.js → index-4wcgvPoF.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-ZRJRItm0.js → index-B0S8NzO6.js} +1 -1
  97. package/src/assets/web-panel/assets/index-B7a1TrU6.js +1 -0
  98. package/src/assets/web-panel/assets/{index-CuS-UPoj.js → index-BUt8kTIB.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BtGxuQrO.js → index-B_EvG_GW.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-B0QArPQt.js → index-BbPtzB8M.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Cd3KuNK5.js → index-BbepULSc.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CbhE3j5j.js → index-BfuKP4qe.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BXd2_LmH.js → index-BiC6dQZG.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CP5alL4t.js → index-BjHBpRYZ.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BvL_3J_n.js → index-BpFJHiTv.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DFyWKOBD.js → index-BydjdZnl.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Ddk0e_Pi.js → index-BzG-x9p4.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BS3M5H9V.js → index-Bzr0rB5T.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-DkHqMnn3.js → index-C229ABfy.js} +1 -1
  110. package/src/assets/web-panel/assets/index-C2B1KRja.js +1 -0
  111. package/src/assets/web-panel/assets/{index-D6GfvEQG.js → index-CFYVQMvu.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BqIhLAbA.js → index-CXkJH-lK.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-B8mkLM4x.js → index-C_H_S-DY.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-D0Ih7Hwn.js → index-C_XuRgGn.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-COe_cOLJ.js → index-C_vRgTl9.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BIP62a6r.js → index-Ck_52dz_.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BP-zkXK8.js → index-CmFNvNLZ.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-D3zCCZRS.js → index-CudmwNBV.js} +3 -3
  119. package/src/assets/web-panel/assets/{index-DFHa1HIg.js → index-Cw0Rjy87.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BvD7b2IK.js → index-D3lD5qap.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DakfFZ-k.js → index-DC_OI9H2.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DvfCEJG-.js → index-DDGaOWBV.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-E1OJRXs4.js → index-DJyN28Et.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-Dmo3dFHb.js → index-DYXHFr4r.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-tKiC8T-4.js → index-Dt5KMjwJ.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-fI5sXMLg.js → index-DuGszaWY.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DUQLXLQM.js → index-DukDVXCv.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DMgnRwrK.js → index-KMqhcF7l.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-F76w1NiL.js → index-KjgKdZe-.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DBFSo1NF.js → index-QXzlT9KD.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BlxEphl7.js → index-vG4XSJ1d.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-9qoVpPt6.js → index-wvb_FtaV.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-ByyvflIR.js → initDefaultProps-BDgd2YZ8.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-B3FQm2By.js → motion-ErtrXdYe.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-BSfns6Ef.js → move-_GPPNCgs.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-CTG1Ieri.js → mtc-parser-DRLL-8V2.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-DObM_2j6.js → omit-p86sl023.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-DOfelQ1t.js → pickAttrs-BTu7cMLH.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-CHZILds_.js → placementArrow-BEKz6Isr.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-REbucKSx.js → responsiveObserve-Ck42c9MP.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-C6EZzD7o.js → slide-1CEvuPsB.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-BxkWS-g3.js → statusUtils-BDfdx1GJ.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-Chklyoq6.js → styleChecker-B4K46m5w.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-CRVwKrrI.js → useFlexGapSupport-DoIVpJNq.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-DV24ik_J.js → useFs-DdAWi-ln.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-C7vIo4Pg.js → usePersonalDataHub-iUu6k8dx.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-By-v5GlF.js → vnode-DZz4R6Tw.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-B1w9Am3r.js → zoom-DXlf9sA3.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/commands/review.js +6 -1
  151. package/src/data/changelog.json +7 -2
  152. package/src/lib/agents.js +19 -0
  153. package/src/lib/background-agent-supervisor.js +34 -7
  154. package/src/lib/docs-drift.js +166 -0
  155. package/src/lib/doctor-checkup.js +76 -0
  156. package/src/lib/hook-event-bus.cjs +0 -0
  157. package/src/lib/json-schema-output.js +30 -1
  158. package/src/lib/json-schema-validate.js +691 -0
  159. package/src/lib/lsp/__tests__/diagnostics-scheduler.test.js +93 -0
  160. package/src/lib/lsp/diagnostics-scheduler.js +127 -0
  161. package/src/lib/operation-fingerprint.js +95 -0
  162. package/src/lib/plugin-runtime/capabilities.js +371 -0
  163. package/src/lib/plugin-runtime/manifest.js +30 -0
  164. package/src/lib/remote-approval-bridge.js +16 -0
  165. package/src/lib/review-pipeline.js +227 -0
  166. package/src/lib/runtime-checkup.js +318 -0
  167. package/src/lib/session-lifecycle.js +305 -0
  168. package/src/lib/settings-hook-events.cjs +39 -13
  169. package/src/lib/subagent-contract.js +383 -0
  170. package/src/lib/telemetry-ids.js +190 -0
  171. package/src/lib/turn-binding.js +397 -0
  172. package/src/runtime/agent-core.js +13 -6
  173. package/src/assets/web-panel/assets/MarkdownRenderer-DxywvhTU.js +0 -1
  174. package/src/assets/web-panel/assets/MobileProjects-Dnt_9-WB.js +0 -1
  175. package/src/assets/web-panel/assets/Projects-Dn-f5aYe.js +0 -1
  176. package/src/assets/web-panel/assets/devWarning-CHDIEOeN.js +0 -1
  177. package/src/assets/web-panel/assets/index-CY1NURWZ.js +0 -1
  178. package/src/assets/web-panel/assets/index-DokUYqpq.js +0 -1
@@ -0,0 +1,691 @@
1
+ /**
2
+ * JSON Schema (Draft 2020-12 subset) validator with STABLE error codes + RFC
3
+ * 6901 JSON Pointers, schema meta-validation, a schema digest, and a
4
+ * `structured_result` stream event (P2 "JSON Schema 结构化输出").
5
+ *
6
+ * The existing [[json-schema-output.js]] validator covers only
7
+ * type/properties/required/items/enum/const/additionalProperties:false and
8
+ * reports `$.path`-style strings. This module is the richer, protocol-facing
9
+ * core:
10
+ *
11
+ * validate(value, schema) → { valid, errors:[{code, keyword, instancePath,
12
+ * schemaPath, message}] } — JSON Pointers + codes
13
+ * validateSchema(schema) → meta-validate the schema itself (startup check)
14
+ * computeSchemaDigest(s) → "sha256:…" over the canonical schema
15
+ * buildStructuredResultEvent({schema, value})
16
+ * → { type:"structured_result", schema_digest,
17
+ * valid, value, errors? }
18
+ *
19
+ * On failure the caller must surface the codes + pointers, never silently fall
20
+ * back to free text. Pure (crypto only hashes the digest); zero deps.
21
+ *
22
+ * Supported keywords: type (+ integer), enum, const, properties, required,
23
+ * additionalProperties (bool|schema), patternProperties-free, items,
24
+ * prefixItems, minItems/maxItems, uniqueItems, minLength/maxLength, pattern,
25
+ * minimum/maximum/exclusiveMinimum/exclusiveMaximum, multipleOf,
26
+ * minProperties/maxProperties, allOf/anyOf/oneOf/not, and local `$ref`
27
+ * (`#/$defs/…`, `#/definitions/…`, or any in-document JSON Pointer).
28
+ */
29
+
30
+ import crypto from "crypto";
31
+
32
+ const KNOWN_TYPES = new Set([
33
+ "object",
34
+ "array",
35
+ "string",
36
+ "number",
37
+ "integer",
38
+ "boolean",
39
+ "null",
40
+ ]);
41
+
42
+ const MAX_REF_DEPTH = 128; // guards recursive $ref against cyclic data
43
+
44
+ /** RFC 6901 JSON Pointer from a segment array ("" = document root). */
45
+ export function jsonPointer(segments) {
46
+ if (!segments || segments.length === 0) return "";
47
+ return (
48
+ "/" +
49
+ segments
50
+ .map((s) => String(s).replace(/~/g, "~0").replace(/\//g, "~1"))
51
+ .join("/")
52
+ );
53
+ }
54
+
55
+ /** JSON value type per Draft 2020-12 (integer is a refinement of number). */
56
+ function typeOf(v) {
57
+ if (v === null) return "null";
58
+ if (Array.isArray(v)) return "array";
59
+ if (typeof v === "number") return Number.isInteger(v) ? "integer" : "number";
60
+ return typeof v;
61
+ }
62
+
63
+ function deepEqual(a, b) {
64
+ return canonical(a) === canonical(b);
65
+ }
66
+
67
+ /** Canonical JSON (sorted keys) — stable across key order for digest + equality. */
68
+ export function canonical(value) {
69
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
70
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
71
+ const keys = Object.keys(value).sort();
72
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${canonical(value[k])}`).join(",")}}`;
73
+ }
74
+
75
+ /** "sha256:<hex>" over the canonical form of the schema. */
76
+ export function computeSchemaDigest(schema) {
77
+ const h = crypto.createHash("sha256");
78
+ h.update(canonical(schema));
79
+ return `sha256:${h.digest("hex")}`;
80
+ }
81
+
82
+ /** Resolve a local `#/...` JSON Pointer $ref within `root`; null if unresolved. */
83
+ function resolveRef(root, ref) {
84
+ if (typeof ref !== "string" || !ref.startsWith("#")) return null;
85
+ const frag = ref.slice(1);
86
+ if (frag === "" || frag === "/") return root;
87
+ const parts = frag
88
+ .replace(/^\//, "")
89
+ .split("/")
90
+ .map((p) => p.replace(/~1/g, "/").replace(/~0/g, "~"));
91
+ let cur = root;
92
+ for (const p of parts) {
93
+ if (cur == null || typeof cur !== "object") return null;
94
+ cur = cur[p];
95
+ }
96
+ return cur === undefined ? null : cur;
97
+ }
98
+
99
+ // ─── instance validation ─────────────────────────────────────────────────────
100
+
101
+ /**
102
+ * Validate `value` against `schema`.
103
+ * @returns {{valid:boolean, errors:Array<{code,keyword,instancePath,schemaPath,message}>}}
104
+ */
105
+ export function validate(value, schema) {
106
+ const errors = [];
107
+ _validate(value, schema, [], [], schema, errors, 0);
108
+ return { valid: errors.length === 0, errors };
109
+ }
110
+
111
+ function _err(errors, keyword, instSegs, schemaSegs, message) {
112
+ errors.push({
113
+ code: keyword,
114
+ keyword,
115
+ instancePath: jsonPointer(instSegs),
116
+ schemaPath: jsonPointer(schemaSegs),
117
+ message,
118
+ });
119
+ }
120
+
121
+ function _validate(value, schema, inst, sch, root, errors, depth) {
122
+ if (schema === true || schema === undefined) return;
123
+ if (schema === false) {
124
+ _err(errors, "false", inst, sch, "schema is `false` — no value is valid");
125
+ return;
126
+ }
127
+ if (!schema || typeof schema !== "object") return;
128
+ if (depth > MAX_REF_DEPTH) return; // cyclic $ref guard
129
+
130
+ // $ref — validate against the referenced schema (local only).
131
+ if (typeof schema.$ref === "string") {
132
+ const target = resolveRef(root, schema.$ref);
133
+ if (target == null) {
134
+ _err(
135
+ errors,
136
+ "$ref",
137
+ inst,
138
+ [...sch, "$ref"],
139
+ `cannot resolve $ref "${schema.$ref}"`,
140
+ );
141
+ } else {
142
+ _validate(value, target, inst, [...sch, "$ref"], root, errors, depth + 1);
143
+ }
144
+ // sibling keywords still apply in 2020-12; fall through.
145
+ }
146
+
147
+ const t = typeOf(value);
148
+
149
+ if (schema.type !== undefined) {
150
+ const want = Array.isArray(schema.type) ? schema.type : [schema.type];
151
+ const ok = want.some((x) => x === t || (x === "number" && t === "integer"));
152
+ if (!ok) {
153
+ _err(
154
+ errors,
155
+ "type",
156
+ inst,
157
+ [...sch, "type"],
158
+ `expected type ${want.join("|")}, got ${t}`,
159
+ );
160
+ return; // type mismatch — deeper checks would be noise
161
+ }
162
+ }
163
+
164
+ if (schema.enum !== undefined) {
165
+ if (
166
+ !Array.isArray(schema.enum) ||
167
+ !schema.enum.some((e) => deepEqual(e, value))
168
+ ) {
169
+ _err(
170
+ errors,
171
+ "enum",
172
+ inst,
173
+ [...sch, "enum"],
174
+ "value is not one of the allowed enum values",
175
+ );
176
+ }
177
+ }
178
+ if (schema.const !== undefined && !deepEqual(schema.const, value)) {
179
+ _err(
180
+ errors,
181
+ "const",
182
+ inst,
183
+ [...sch, "const"],
184
+ `value must equal ${JSON.stringify(schema.const)}`,
185
+ );
186
+ }
187
+
188
+ if (t === "string") _validateString(value, schema, inst, sch, errors);
189
+ if (t === "number" || t === "integer")
190
+ _validateNumber(value, schema, inst, sch, errors);
191
+ if (t === "array")
192
+ _validateArray(value, schema, inst, sch, root, errors, depth);
193
+ if (t === "object")
194
+ _validateObject(value, schema, inst, sch, root, errors, depth);
195
+
196
+ _validateCombinators(value, schema, inst, sch, root, errors, depth);
197
+ }
198
+
199
+ function _validateString(value, schema, inst, sch, errors) {
200
+ if (Number.isFinite(schema.minLength) && value.length < schema.minLength) {
201
+ _err(
202
+ errors,
203
+ "minLength",
204
+ inst,
205
+ [...sch, "minLength"],
206
+ `string is shorter than minLength ${schema.minLength}`,
207
+ );
208
+ }
209
+ if (Number.isFinite(schema.maxLength) && value.length > schema.maxLength) {
210
+ _err(
211
+ errors,
212
+ "maxLength",
213
+ inst,
214
+ [...sch, "maxLength"],
215
+ `string is longer than maxLength ${schema.maxLength}`,
216
+ );
217
+ }
218
+ if (typeof schema.pattern === "string") {
219
+ let re;
220
+ try {
221
+ re = new RegExp(schema.pattern);
222
+ } catch {
223
+ re = null;
224
+ }
225
+ if (re && !re.test(value)) {
226
+ _err(
227
+ errors,
228
+ "pattern",
229
+ inst,
230
+ [...sch, "pattern"],
231
+ `string does not match pattern ${schema.pattern}`,
232
+ );
233
+ }
234
+ }
235
+ }
236
+
237
+ function _validateNumber(value, schema, inst, sch, errors) {
238
+ if (Number.isFinite(schema.minimum) && value < schema.minimum) {
239
+ _err(
240
+ errors,
241
+ "minimum",
242
+ inst,
243
+ [...sch, "minimum"],
244
+ `value is less than minimum ${schema.minimum}`,
245
+ );
246
+ }
247
+ if (Number.isFinite(schema.maximum) && value > schema.maximum) {
248
+ _err(
249
+ errors,
250
+ "maximum",
251
+ inst,
252
+ [...sch, "maximum"],
253
+ `value is greater than maximum ${schema.maximum}`,
254
+ );
255
+ }
256
+ if (
257
+ Number.isFinite(schema.exclusiveMinimum) &&
258
+ value <= schema.exclusiveMinimum
259
+ ) {
260
+ _err(
261
+ errors,
262
+ "exclusiveMinimum",
263
+ inst,
264
+ [...sch, "exclusiveMinimum"],
265
+ `value must be > ${schema.exclusiveMinimum}`,
266
+ );
267
+ }
268
+ if (
269
+ Number.isFinite(schema.exclusiveMaximum) &&
270
+ value >= schema.exclusiveMaximum
271
+ ) {
272
+ _err(
273
+ errors,
274
+ "exclusiveMaximum",
275
+ inst,
276
+ [...sch, "exclusiveMaximum"],
277
+ `value must be < ${schema.exclusiveMaximum}`,
278
+ );
279
+ }
280
+ if (Number.isFinite(schema.multipleOf) && schema.multipleOf > 0) {
281
+ const q = value / schema.multipleOf;
282
+ if (Math.abs(q - Math.round(q)) > 1e-9) {
283
+ _err(
284
+ errors,
285
+ "multipleOf",
286
+ inst,
287
+ [...sch, "multipleOf"],
288
+ `value is not a multiple of ${schema.multipleOf}`,
289
+ );
290
+ }
291
+ }
292
+ }
293
+
294
+ function _validateArray(value, schema, inst, sch, root, errors, depth) {
295
+ if (Number.isFinite(schema.minItems) && value.length < schema.minItems) {
296
+ _err(
297
+ errors,
298
+ "minItems",
299
+ inst,
300
+ [...sch, "minItems"],
301
+ `array has fewer than minItems ${schema.minItems}`,
302
+ );
303
+ }
304
+ if (Number.isFinite(schema.maxItems) && value.length > schema.maxItems) {
305
+ _err(
306
+ errors,
307
+ "maxItems",
308
+ inst,
309
+ [...sch, "maxItems"],
310
+ `array has more than maxItems ${schema.maxItems}`,
311
+ );
312
+ }
313
+ if (schema.uniqueItems === true) {
314
+ const seen = new Set();
315
+ for (const item of value) {
316
+ const key = canonical(item);
317
+ if (seen.has(key)) {
318
+ _err(
319
+ errors,
320
+ "uniqueItems",
321
+ inst,
322
+ [...sch, "uniqueItems"],
323
+ "array items are not unique",
324
+ );
325
+ break;
326
+ }
327
+ seen.add(key);
328
+ }
329
+ }
330
+ const prefix = Array.isArray(schema.prefixItems) ? schema.prefixItems : [];
331
+ value.forEach((item, i) => {
332
+ if (i < prefix.length) {
333
+ _validate(
334
+ item,
335
+ prefix[i],
336
+ [...inst, i],
337
+ [...sch, "prefixItems", i],
338
+ root,
339
+ errors,
340
+ depth,
341
+ );
342
+ } else if (schema.items !== undefined) {
343
+ _validate(
344
+ item,
345
+ schema.items,
346
+ [...inst, i],
347
+ [...sch, "items"],
348
+ root,
349
+ errors,
350
+ depth,
351
+ );
352
+ }
353
+ });
354
+ }
355
+
356
+ function _validateObject(value, schema, inst, sch, root, errors, depth) {
357
+ const keys = Object.keys(value);
358
+ if (
359
+ Number.isFinite(schema.minProperties) &&
360
+ keys.length < schema.minProperties
361
+ ) {
362
+ _err(
363
+ errors,
364
+ "minProperties",
365
+ inst,
366
+ [...sch, "minProperties"],
367
+ `object has fewer than minProperties ${schema.minProperties}`,
368
+ );
369
+ }
370
+ if (
371
+ Number.isFinite(schema.maxProperties) &&
372
+ keys.length > schema.maxProperties
373
+ ) {
374
+ _err(
375
+ errors,
376
+ "maxProperties",
377
+ inst,
378
+ [...sch, "maxProperties"],
379
+ `object has more than maxProperties ${schema.maxProperties}`,
380
+ );
381
+ }
382
+ for (const req of schema.required || []) {
383
+ if (!Object.prototype.hasOwnProperty.call(value, req)) {
384
+ _err(
385
+ errors,
386
+ "required",
387
+ inst,
388
+ [...sch, "required"],
389
+ `missing required property "${req}"`,
390
+ );
391
+ }
392
+ }
393
+ const props = schema.properties || {};
394
+ for (const [k, v] of Object.entries(value)) {
395
+ if (Object.prototype.hasOwnProperty.call(props, k)) {
396
+ _validate(
397
+ v,
398
+ props[k],
399
+ [...inst, k],
400
+ [...sch, "properties", k],
401
+ root,
402
+ errors,
403
+ depth,
404
+ );
405
+ } else if (schema.additionalProperties === false) {
406
+ _err(
407
+ errors,
408
+ "additionalProperties",
409
+ [...inst, k],
410
+ [...sch, "additionalProperties"],
411
+ `unexpected property "${k}"`,
412
+ );
413
+ } else if (
414
+ schema.additionalProperties &&
415
+ typeof schema.additionalProperties === "object"
416
+ ) {
417
+ _validate(
418
+ v,
419
+ schema.additionalProperties,
420
+ [...inst, k],
421
+ [...sch, "additionalProperties"],
422
+ root,
423
+ errors,
424
+ depth,
425
+ );
426
+ }
427
+ }
428
+ }
429
+
430
+ function _branchValid(value, subschema, root, depth) {
431
+ const errs = [];
432
+ _validate(value, subschema, [], [], root, errs, depth + 1);
433
+ return errs.length === 0;
434
+ }
435
+
436
+ function _validateCombinators(value, schema, inst, sch, root, errors, depth) {
437
+ if (Array.isArray(schema.allOf)) {
438
+ schema.allOf.forEach((s, i) => {
439
+ _validate(value, s, inst, [...sch, "allOf", i], root, errors, depth);
440
+ });
441
+ }
442
+ if (Array.isArray(schema.anyOf)) {
443
+ const ok = schema.anyOf.some((s) => _branchValid(value, s, root, depth));
444
+ if (!ok)
445
+ _err(
446
+ errors,
447
+ "anyOf",
448
+ inst,
449
+ [...sch, "anyOf"],
450
+ "value does not match any of the anyOf schemas",
451
+ );
452
+ }
453
+ if (Array.isArray(schema.oneOf)) {
454
+ const matches = schema.oneOf.filter((s) =>
455
+ _branchValid(value, s, root, depth),
456
+ ).length;
457
+ if (matches !== 1) {
458
+ _err(
459
+ errors,
460
+ "oneOf",
461
+ inst,
462
+ [...sch, "oneOf"],
463
+ `value matched ${matches} oneOf schemas (must match exactly 1)`,
464
+ );
465
+ }
466
+ }
467
+ if (
468
+ schema.not !== undefined &&
469
+ _branchValid(value, schema.not, root, depth)
470
+ ) {
471
+ _err(
472
+ errors,
473
+ "not",
474
+ inst,
475
+ [...sch, "not"],
476
+ "value must NOT match the `not` schema",
477
+ );
478
+ }
479
+ }
480
+
481
+ // ─── schema meta-validation (startup) ────────────────────────────────────────
482
+
483
+ /**
484
+ * Meta-validate a schema itself — the "启动时校验 schema" check. Rejects a
485
+ * malformed schema (bad type value, non-array required, non-number numeric
486
+ * keyword, invalid regex, non-object properties, …) so a broken contract fails
487
+ * fast instead of silently mis-validating every value.
488
+ *
489
+ * @returns {{valid:boolean, errors:Array<{code, schemaPath, message}>}}
490
+ */
491
+ export function validateSchema(schema) {
492
+ const errors = [];
493
+ _metaValidate(schema, [], errors, 0);
494
+ return { valid: errors.length === 0, errors };
495
+ }
496
+
497
+ function _metaErr(errors, code, segs, message) {
498
+ errors.push({ code, schemaPath: jsonPointer(segs), message });
499
+ }
500
+
501
+ function _metaValidate(schema, segs, errors, depth) {
502
+ if (schema === true || schema === false) return; // boolean schemas are valid
503
+ if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
504
+ _metaErr(errors, "schema", segs, "schema must be an object or a boolean");
505
+ return;
506
+ }
507
+ if (depth > MAX_REF_DEPTH) return;
508
+
509
+ if (schema.type !== undefined) {
510
+ const types = Array.isArray(schema.type) ? schema.type : [schema.type];
511
+ for (const x of types) {
512
+ if (!KNOWN_TYPES.has(x)) {
513
+ _metaErr(errors, "type", [...segs, "type"], `unknown type "${x}"`);
514
+ }
515
+ }
516
+ }
517
+ if (schema.required !== undefined) {
518
+ if (
519
+ !Array.isArray(schema.required) ||
520
+ schema.required.some((r) => typeof r !== "string")
521
+ ) {
522
+ _metaErr(
523
+ errors,
524
+ "required",
525
+ [...segs, "required"],
526
+ "required must be an array of strings",
527
+ );
528
+ }
529
+ }
530
+ if (schema.enum !== undefined && !Array.isArray(schema.enum)) {
531
+ _metaErr(errors, "enum", [...segs, "enum"], "enum must be an array");
532
+ }
533
+ for (const k of [
534
+ "minimum",
535
+ "maximum",
536
+ "exclusiveMinimum",
537
+ "exclusiveMaximum",
538
+ "multipleOf",
539
+ ]) {
540
+ if (schema[k] !== undefined && typeof schema[k] !== "number") {
541
+ _metaErr(errors, k, [...segs, k], `${k} must be a number`);
542
+ }
543
+ }
544
+ if (
545
+ schema.multipleOf !== undefined &&
546
+ typeof schema.multipleOf === "number" &&
547
+ schema.multipleOf <= 0
548
+ ) {
549
+ _metaErr(
550
+ errors,
551
+ "multipleOf",
552
+ [...segs, "multipleOf"],
553
+ "multipleOf must be > 0",
554
+ );
555
+ }
556
+ for (const k of [
557
+ "minLength",
558
+ "maxLength",
559
+ "minItems",
560
+ "maxItems",
561
+ "minProperties",
562
+ "maxProperties",
563
+ ]) {
564
+ if (
565
+ schema[k] !== undefined &&
566
+ (!Number.isInteger(schema[k]) || schema[k] < 0)
567
+ ) {
568
+ _metaErr(errors, k, [...segs, k], `${k} must be a non-negative integer`);
569
+ }
570
+ }
571
+ if (schema.pattern !== undefined) {
572
+ if (typeof schema.pattern !== "string") {
573
+ _metaErr(
574
+ errors,
575
+ "pattern",
576
+ [...segs, "pattern"],
577
+ "pattern must be a string",
578
+ );
579
+ } else {
580
+ try {
581
+ new RegExp(schema.pattern);
582
+ } catch (e) {
583
+ _metaErr(
584
+ errors,
585
+ "pattern",
586
+ [...segs, "pattern"],
587
+ `pattern is not a valid regex: ${e.message}`,
588
+ );
589
+ }
590
+ }
591
+ }
592
+ if (schema.$ref !== undefined && typeof schema.$ref !== "string") {
593
+ _metaErr(errors, "$ref", [...segs, "$ref"], "$ref must be a string");
594
+ }
595
+ if (schema.properties !== undefined) {
596
+ if (
597
+ typeof schema.properties !== "object" ||
598
+ Array.isArray(schema.properties)
599
+ ) {
600
+ _metaErr(
601
+ errors,
602
+ "properties",
603
+ [...segs, "properties"],
604
+ "properties must be an object",
605
+ );
606
+ } else {
607
+ for (const [k, sub] of Object.entries(schema.properties)) {
608
+ _metaValidate(sub, [...segs, "properties", k], errors, depth + 1);
609
+ }
610
+ }
611
+ }
612
+ if (
613
+ schema.additionalProperties !== undefined &&
614
+ typeof schema.additionalProperties === "object"
615
+ ) {
616
+ _metaValidate(
617
+ schema.additionalProperties,
618
+ [...segs, "additionalProperties"],
619
+ errors,
620
+ depth + 1,
621
+ );
622
+ }
623
+ if (schema.items !== undefined) {
624
+ _metaValidate(schema.items, [...segs, "items"], errors, depth + 1);
625
+ }
626
+ if (schema.prefixItems !== undefined) {
627
+ if (!Array.isArray(schema.prefixItems)) {
628
+ _metaErr(
629
+ errors,
630
+ "prefixItems",
631
+ [...segs, "prefixItems"],
632
+ "prefixItems must be an array of schemas",
633
+ );
634
+ } else {
635
+ schema.prefixItems.forEach((sub, i) =>
636
+ _metaValidate(sub, [...segs, "prefixItems", i], errors, depth + 1),
637
+ );
638
+ }
639
+ }
640
+ for (const k of ["allOf", "anyOf", "oneOf"]) {
641
+ if (schema[k] !== undefined) {
642
+ if (!Array.isArray(schema[k])) {
643
+ _metaErr(errors, k, [...segs, k], `${k} must be an array of schemas`);
644
+ } else {
645
+ schema[k].forEach((sub, i) =>
646
+ _metaValidate(sub, [...segs, k, i], errors, depth + 1),
647
+ );
648
+ }
649
+ }
650
+ }
651
+ if (schema.not !== undefined)
652
+ _metaValidate(schema.not, [...segs, "not"], errors, depth + 1);
653
+ for (const defsKey of ["$defs", "definitions"]) {
654
+ if (schema[defsKey] !== undefined) {
655
+ if (
656
+ typeof schema[defsKey] !== "object" ||
657
+ Array.isArray(schema[defsKey])
658
+ ) {
659
+ _metaErr(
660
+ errors,
661
+ defsKey,
662
+ [...segs, defsKey],
663
+ `${defsKey} must be an object`,
664
+ );
665
+ } else {
666
+ for (const [k, sub] of Object.entries(schema[defsKey])) {
667
+ _metaValidate(sub, [...segs, defsKey, k], errors, depth + 1);
668
+ }
669
+ }
670
+ }
671
+ }
672
+ }
673
+
674
+ // ─── structured_result stream event ──────────────────────────────────────────
675
+
676
+ /**
677
+ * Build the terminal `structured_result` stream event. Carries the schema
678
+ * digest (so a consumer can pin the contract), the validity, the value, and —
679
+ * when invalid — the coded/pointered errors. Never returns free text.
680
+ */
681
+ export function buildStructuredResultEvent({ schema, value }) {
682
+ const { valid, errors } = validate(value, schema);
683
+ const event = {
684
+ type: "structured_result",
685
+ schema_digest: computeSchemaDigest(schema),
686
+ valid,
687
+ value,
688
+ };
689
+ if (!valid) event.errors = errors;
690
+ return event;
691
+ }