@openclaw/matrix 2026.9.8 → 2026.10.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.setup/{account-selection-B7axQ80R.mjs → account-selection-BDeeqwwR.mjs} +1 -1
- package/dist/.setup/{accounts-WkgrIxMt.mjs → accounts-C_r0UlEm.mjs} +2 -2
- package/dist/.setup/{approval-handler.runtime-C-pw3NvY.mjs → approval-handler.runtime-QkHLH2az.mjs} +14 -19
- package/dist/.setup/{approval-reactions-BrS5ECU0.mjs → approval-reactions-DhB6gNPU.mjs} +11 -25
- package/dist/.setup/{channel-DXenXmj0.mjs → channel-CeRXEAEP.mjs} +17 -46
- package/dist/.setup/{channel.runtime-BXUawOno.mjs → channel.runtime-DBQA2y1F.mjs} +6 -6
- package/dist/.setup/{channel.setup-DWfLaXqT.mjs → channel.setup-DC2t7_PK.mjs} +12 -26
- package/dist/.setup/{cli-IhZO2OEj.mjs → cli-Be8tdNw8.mjs} +24 -45
- package/dist/.setup/{cli-metadata-nowEgdY0.mjs → cli-metadata-CtcjBFhc.mjs} +1 -1
- package/dist/.setup/{client-BXATebyo.mjs → client-DY3HExqI.mjs} +3 -3
- package/dist/.setup/{client-bootstrap-BiHX55is.mjs → client-bootstrap-CZvJjr29.mjs} +1 -1
- package/dist/.setup/{client-Ccv77kwh.mjs → client-kmih04ng.mjs} +21 -40
- package/dist/.setup/{client-support-Bn9Bk0-H.mjs → client-support-D7BlioUb.mjs} +14 -23
- package/dist/.setup/{config-update-5m1Un5gJ.mjs → config-update-CZndPxNd.mjs} +29 -72
- package/dist/.setup/{create-client-DRZ580E3.mjs → create-client-CbJVyFDy.mjs} +5 -5
- package/dist/.setup/{credentials-C9qDO5-2.mjs → credentials-C2dvc_kB.mjs} +1 -1
- package/dist/.setup/{credentials-read-KD4o5biZ.mjs → credentials-read-CqRiEAQa.mjs} +1 -1
- package/dist/.setup/{crypto-runtime-DPjIDF8H.mjs → crypto-runtime-B2AjWo-i.mjs} +223 -79
- package/dist/.setup/{deps-CLQ4EOq7.mjs → deps-CFNl7tQo.mjs} +14 -39
- package/dist/.setup/{device-health-U-yoVjPw.mjs → device-health-Be60VF1w.mjs} +1 -1
- package/dist/.setup/{direct-management-Cn2t8n1V.mjs → direct-management-DJtQhLKH.mjs} +4 -8
- package/dist/.setup/{directory-live-_sw-Q7KO.mjs → directory-live-DW5UykLL.mjs} +3 -3
- package/dist/.setup/{doctor-contract-De6geW0h.mjs → doctor-contract-CsTNmbMa.mjs} +10 -133
- package/dist/.setup/{draft-stream-CdVMstpR.mjs → draft-stream-B87DfA6a.mjs} +4 -8
- package/dist/.setup/{encryption-guidance-B6797jNA.mjs → encryption-guidance-BEjKbiMR.mjs} +1 -1
- package/dist/.setup/{exec-approvals-fsiMQ1ce.mjs → exec-approvals-BLDAMyHs.mjs} +6 -19
- package/dist/.setup/{file-sync-store-B-9bMb_O.mjs → file-sync-store-Clc9iEdn.mjs} +3 -3
- package/dist/.setup/{http-client-C1XvVD3K.mjs → http-client-DfJY5Ck0.mjs} +8 -29
- package/dist/.setup/{inbound-dedupe-BGrMrTTu.mjs → inbound-dedupe-C-EBGY0B.mjs} +1 -1
- package/dist/.setup/{joined-room-encryption-TZoOKXgh.mjs → joined-room-encryption-BAD70N5n.mjs} +1 -1
- package/dist/.setup/logger-CXQnpXCt.mjs +44 -0
- package/dist/.setup/{logging-mhnFQGzB.mjs → logging-BKV8TYQq.mjs} +7 -32
- package/dist/.setup/{messages-Buz27pi5.mjs → messages-uCbwLRKS.mjs} +5 -8
- package/dist/.setup/{monitor-BBg5qgov.mjs → monitor-skIntQVG.mjs} +109 -180
- package/dist/.setup/{onboarding-hJaieQj5.mjs → onboarding-Cm_tOJxs.mjs} +12 -19
- package/dist/.setup/{outbound-C9vBijaH.mjs → outbound-CqQou3ny.mjs} +16 -22
- package/dist/.setup/{profile-B3DD2jYa.mjs → profile-DS0xdJAi.mjs} +11 -31
- package/dist/.setup/{profile-update-CmxIAd4c.mjs → profile-update-C1n8SRqH.mjs} +3 -3
- package/dist/.setup/{reaction-events-mnzc_JvP.mjs → reaction-events-Cqq46xsG.mjs} +5 -5
- package/dist/.setup/{resolve-targets-BFq3q4c9.mjs → resolve-targets-DFeU1Ww6.mjs} +2 -2
- package/dist/.setup/retired-state-BXUQ2I-C.mjs +91 -0
- package/dist/.setup/{room-info-BbTGRJcR.mjs → room-info-BPMbwe8I.mjs} +33 -50
- package/dist/.setup/{sdk-DmRVM0VA.mjs → sdk-CgQGkCsS.mjs} +226 -182
- package/dist/.setup/{send-GOF64QRc.mjs → send-B1Y2L4wj.mjs} +19 -68
- package/dist/.setup/{setup-bootstrap-AzalcuCW.mjs → setup-bootstrap-UNIGyKnk.mjs} +2 -2
- package/dist/.setup/{setup-core-BeifoeL4.mjs → setup-core-6DppLENo.mjs} +5 -5
- package/dist/.setup/{setup-plugin-api-Bsbdw41x.mjs → setup-plugin-api-BRs9bcp4.mjs} +1 -1
- package/dist/.setup/startup-verification-D00eUt74.mjs +122 -0
- package/dist/.setup/storage-D7agewjH.mjs +464 -0
- package/dist/.setup/{sync-cache-state-C6sEmvJK.mjs → sync-cache-state-C2z64uyk.mjs} +10 -24
- package/dist/.setup/{thread-bindings-jXu_9cHE.mjs → thread-bindings-DveHVZqN.mjs} +13 -71
- package/dist/.setup/{tool-actions-Ce7Okg6m.mjs → tool-actions-BqlK2ilM.mjs} +51 -73
- package/dist/.setup/{verification-C45rOZkM.mjs → verification-kMlFYUn0.mjs} +10 -27
- package/dist/api.js +5 -5
- package/dist/channel-plugin-api.js +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/contract-api.js +2 -2
- package/dist/doctor-contract-api.js +47 -201
- package/dist/helper-api.js +1 -1
- package/dist/index.js +1 -1
- package/dist/plugin-entry.handlers.runtime.js +1 -1
- package/dist/runtime-api.js +3 -3
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-entry.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/node_modules/@openclaw/fs-safe/CHANGELOG.md +95 -0
- package/node_modules/@openclaw/fs-safe/README.md +70 -379
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.js +35 -51
- package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.js +9 -10
- package/node_modules/@openclaw/fs-safe/dist/archive.js +2 -5
- package/node_modules/@openclaw/fs-safe/dist/atomic-io.d.ts +51 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic-io.js +242 -0
- package/node_modules/@openclaw/fs-safe/dist/config.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/config.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/copy-tree-portable.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/create.js +12 -5
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts +11 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +4 -7
- package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.d.ts +55 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication.js +262 -0
- package/node_modules/@openclaw/fs-safe/dist/exclusive-create.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/exclusive-create.js +22 -0
- package/node_modules/@openclaw/fs-safe/dist/file-cleanup.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/file-cleanup.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/file-identity.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-io.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-mutation.js +9 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root.js +4 -6
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-stale-admission.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +8 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.js +20 -18
- package/node_modules/@openclaw/fs-safe/dist/file-store.js +4 -10
- package/node_modules/@openclaw/fs-safe/dist/fs.d.ts +2 -10
- package/node_modules/@openclaw/fs-safe/dist/fs.js +2 -10
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +3 -4
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +6 -18
- package/node_modules/@openclaw/fs-safe/dist/guest-dispatch-python.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +0 -2
- package/node_modules/@openclaw/fs-safe/dist/guest.js +3 -9
- package/node_modules/@openclaw/fs-safe/dist/index.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/index.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.js +1 -5
- package/node_modules/@openclaw/fs-safe/dist/json.js +19 -37
- package/node_modules/@openclaw/fs-safe/dist/move-path.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/mutation-authority.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/mutation-authority.js +9 -1
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +47 -2
- package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +1 -9
- package/node_modules/@openclaw/fs-safe/dist/native-config.js +6 -40
- package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.js +5 -2
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +11 -316
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.d.ts +7 -7
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.js +28 -175
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.js +418 -0
- package/node_modules/@openclaw/fs-safe/dist/native-rename-outcome.js +9 -4
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +17 -13
- package/node_modules/@openclaw/fs-safe/dist/native-staged-symlink.js +6 -24
- package/node_modules/@openclaw/fs-safe/dist/native.js +5 -1
- package/node_modules/@openclaw/fs-safe/dist/path-case.js +10 -9
- package/node_modules/@openclaw/fs-safe/dist/path-scope-lexical.js +4 -1
- package/node_modules/@openclaw/fs-safe/dist/path-segment-route.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/path-segment-route.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/path.js +4 -1
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/pinned-mutation-admission.js +1 -3
- package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +9 -10
- package/node_modules/@openclaw/fs-safe/dist/private-producer-handoff.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/publish-file.js +4 -3
- package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.d.ts +3 -4
- package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.js +18 -32
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts +5 -17
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.js +92 -230
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts +4 -15
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.js +22 -63
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts +9 -34
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +78 -83
- package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.d.ts +18 -20
- package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.js +64 -98
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts +16 -33
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.js +61 -200
- package/node_modules/@openclaw/fs-safe/dist/replace-file-types.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/replace-file.js +76 -216
- package/node_modules/@openclaw/fs-safe/dist/root-boundary.js +14 -24
- package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts +1 -4
- package/node_modules/@openclaw/fs-safe/dist/root-context.js +4 -19
- package/node_modules/@openclaw/fs-safe/dist/root-create-native.d.ts +52 -0
- package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +350 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +35 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.d.ts +2 -27
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +31 -28
- package/node_modules/@openclaw/fs-safe/dist/root-directory.js +1 -4
- package/node_modules/@openclaw/fs-safe/dist/root-errors.js +34 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.js +9 -21
- package/node_modules/@openclaw/fs-safe/dist/root-impl.js +105 -37
- package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.d.ts +7 -2
- package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.js +67 -38
- package/node_modules/@openclaw/fs-safe/dist/root-observed-path.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/root-observed-path.js +0 -2
- package/node_modules/@openclaw/fs-safe/dist/root-options.d.ts +2 -3
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/root-path-stat.js +68 -85
- package/node_modules/@openclaw/fs-safe/dist/root-path.js +6 -1
- package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/root-paths.js +4 -9
- package/node_modules/@openclaw/fs-safe/dist/root-remove-native.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove-native.js +311 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove.d.ts +11 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts +2 -2
- package/node_modules/@openclaw/fs-safe/dist/root-walk.js +1 -3
- package/node_modules/@openclaw/fs-safe/dist/root-write-admission.d.ts +3 -3
- package/node_modules/@openclaw/fs-safe/dist/root-write-admission.js +8 -10
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.js +0 -4
- package/node_modules/@openclaw/fs-safe/dist/secret-file.js +12 -9
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts +0 -2
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.js +7 -4
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.js +13 -6
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts +0 -3
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +5 -23
- package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.d.ts +2 -1
- package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.js +11 -6
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.js +1 -8
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.js +2 -9
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/trash.js +6 -2
- package/node_modules/@openclaw/fs-safe/dist/walk.js +100 -46
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.js +235 -19
- package/node_modules/@openclaw/fs-safe/dist/watch-native.d.ts +21 -2
- package/node_modules/@openclaw/fs-safe/dist/watch-native.js +21 -3
- package/node_modules/@openclaw/fs-safe/dist/watch-rescan.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-rescan.js +111 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.js +27 -4
- package/node_modules/@openclaw/fs-safe/dist/watch-stream.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/watch.js +131 -40
- package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.js +24 -6
- package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.js +51 -0
- package/node_modules/@openclaw/fs-safe/docs/advanced.md +4 -0
- package/node_modules/@openclaw/fs-safe/docs/atomic.md +4 -1
- package/node_modules/@openclaw/fs-safe/docs/config.md +6 -14
- package/node_modules/@openclaw/fs-safe/docs/contributing.md +4 -14
- package/node_modules/@openclaw/fs-safe/docs/durability.md +6 -29
- package/node_modules/@openclaw/fs-safe/docs/entry-publication.md +146 -0
- package/node_modules/@openclaw/fs-safe/docs/errors.md +16 -0
- package/node_modules/@openclaw/fs-safe/docs/file-store.md +28 -5
- package/node_modules/@openclaw/fs-safe/docs/index.md +2 -31
- package/node_modules/@openclaw/fs-safe/docs/install.md +10 -31
- package/node_modules/@openclaw/fs-safe/docs/json.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/local-roots.md +0 -1
- package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +12 -12
- package/node_modules/@openclaw/fs-safe/docs/native-helper.md +35 -96
- package/node_modules/@openclaw/fs-safe/docs/native.md +22 -20
- package/node_modules/@openclaw/fs-safe/docs/path.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/permissions.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/public-api.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/reading.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/root.md +26 -184
- package/node_modules/@openclaw/fs-safe/docs/secret-file.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/security-model.md +115 -3
- package/node_modules/@openclaw/fs-safe/docs/store.md +2 -2
- package/node_modules/@openclaw/fs-safe/docs/temp.md +29 -65
- package/node_modules/@openclaw/fs-safe/docs/testing.md +90 -58
- package/node_modules/@openclaw/fs-safe/docs/types.md +3 -16
- package/node_modules/@openclaw/fs-safe/docs/walk.md +33 -5
- package/node_modules/@openclaw/fs-safe/docs/watch.md +96 -14
- package/node_modules/@openclaw/fs-safe/docs/writing.md +172 -16
- package/node_modules/@openclaw/fs-safe/package.json +10 -10
- package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
- package/openclaw.plugin.json +0 -9
- package/package.json +5 -5
- package/dist/.setup/crypto-snapshot-doctor.runtime-44FrCPR7.mjs +0 -91
- package/dist/.setup/doctor-DMvEBx6o.mjs +0 -49
- package/dist/.setup/idb-persistence-DBvfre1X.mjs +0 -227
- package/dist/.setup/idb-persistence-lock-D_mDu4Cf.mjs +0 -27
- package/dist/.setup/logger-CVv56jzH.mjs +0 -74
- package/dist/.setup/startup-verification-Aiy_xVdI.mjs +0 -204
- package/dist/.setup/storage-BXS2cB2i.mjs +0 -288
- package/dist/.setup/storage-metadata-BDRZ7vpX.mjs +0 -371
- package/node_modules/@openclaw/fs-safe/dist/watch-alias.d.ts +0 -6
- package/node_modules/@openclaw/fs-safe/dist/watch-alias.js +0 -88
- package/node_modules/@openclaw/fs-safe/docs/mutation-policy-proof.md +0 -69
- package/node_modules/@openclaw/fs-safe/docs/private-file-store.md +0 -68
- package/node_modules/@openclaw/fs-safe/docs/test-hooks.md +0 -110
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as normalizeCompatibilityConfig, r as runtime_doctor_migrations_exports, t as legacyConfigRules } from "./.setup/doctor-contract-
|
|
1
|
+
import { n as normalizeCompatibilityConfig, r as runtime_doctor_migrations_exports, t as legacyConfigRules } from "./.setup/doctor-contract-CsTNmbMa.mjs";
|
|
2
2
|
import { i as normalizeMatrixStoredCredentials, n as isMatrixCredentialRevocation, r as matrixCredentialsStoreKey, t as MATRIX_CREDENTIALS_NAMESPACE } from "./.setup/credentials-state-B3cuUFwZ.mjs";
|
|
3
3
|
import { c as resolveMatrixStateLayoutChildDepth, i as resolveMatrixCredentialsDir } from "./.setup/storage-paths-B51JM-pC.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { a as describeRetiredMatrixState, o as resolveMatrixSqliteStateEnv, t as RETIRED_MATRIX_STATE_FILENAMES } from "./.setup/retired-state-BXUQ2I-C.mjs";
|
|
5
|
+
import { i as readLegacyMatrixSyncCacheState, n as hasMatrixSyncCacheStateInStore, r as openMatrixSyncCacheStoreOptions, s as writeMatrixSyncCacheStateToStore } from "./.setup/sync-cache-state-C2z64uyk.mjs";
|
|
6
6
|
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
7
7
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
@@ -35,8 +35,10 @@ async function walkMatrixStateFiles(stateDir, includeFile, stateRootDepths = [])
|
|
|
35
35
|
//#region extensions/matrix/src/matrix/account-state-schema-doctor.ts
|
|
36
36
|
const STATE_DATABASE_FILENAME = "openclaw.sqlite";
|
|
37
37
|
async function collectMatrixAccountStateRoots(stateDir) {
|
|
38
|
-
const { entries, failedDirs } = await walkMatrixStateFiles(stateDir, (name, depth) => depth === 5 && name === STATE_DATABASE_FILENAME, [2, 4]);
|
|
38
|
+
const { entries, failedDirs } = await walkMatrixStateFiles(stateDir, (name, depth) => depth === 5 && name === STATE_DATABASE_FILENAME || (depth === 0 || depth === 2 || depth === 4) && RETIRED_MATRIX_STATE_FILENAMES.has(name), [2, 4]);
|
|
39
39
|
if (failedDirs.length > 0) throw failedDirs[0].error;
|
|
40
|
+
const retired = entries.filter((entry) => path.basename(entry.path) !== STATE_DATABASE_FILENAME);
|
|
41
|
+
if (retired.length > 0) throw new Error(retired.map((entry) => describeRetiredMatrixState(entry.path)).join("\n"));
|
|
40
42
|
return entries.map((entry) => path.dirname(path.dirname(entry.path))).toSorted();
|
|
41
43
|
}
|
|
42
44
|
function describeMatrixAccountStateMigration(storageRootDir, migration) {
|
|
@@ -81,12 +83,10 @@ const matrixAccountStateSchemaMigration = {
|
|
|
81
83
|
//#region extensions/matrix/src/matrix/monitor/inbound-dedupe-migration.ts
|
|
82
84
|
const LEGACY_SQLITE_NAMESPACE = "inbound-dedupe";
|
|
83
85
|
const LEGACY_MARKERS_NAMESPACE = "inbound-dedupe-migrations";
|
|
84
|
-
const LEGACY_JSON_VERSION = 1;
|
|
85
86
|
const MATRIX_PLUGIN_ID = "matrix";
|
|
86
87
|
const MIGRATION_COMPLETION_NAMESPACE = "inbound-dedupe-migration-state";
|
|
87
88
|
const MIGRATION_COMPLETION_KEY = "sqlite-json-to-claimable-v1";
|
|
88
89
|
const STATE_DATABASE_RELATIVE_PATH = path.join("state", "openclaw.sqlite");
|
|
89
|
-
const STORAGE_META_FILENAME = "storage-meta.json";
|
|
90
90
|
const MATRIX_LEGACY_INBOUND_DEDUPE_FILENAME = "inbound-dedupe.json";
|
|
91
91
|
function openMatrixInboundDedupeMigrationCompletionStore(context, env) {
|
|
92
92
|
return context.openPluginStateKeyedStore({
|
|
@@ -120,20 +120,16 @@ async function reserveMatrixInboundDedupeMigrationCompletion(context, env) {
|
|
|
120
120
|
async function collectMatrixInboundDedupeSources(stateDir) {
|
|
121
121
|
const matrixRoot = path.resolve(stateDir, "matrix");
|
|
122
122
|
const sqliteRoots = /* @__PURE__ */ new Set();
|
|
123
|
-
const
|
|
124
|
-
const { entries, failedDirs } = await walkMatrixStateFiles(stateDir, (name, depth) => (depth === 0 || depth === 2 || depth === 4) && name === "inbound-dedupe.json" || depth === 5 && name === "openclaw.sqlite", [
|
|
123
|
+
const { entries, failedDirs } = await walkMatrixStateFiles(stateDir, (name, depth) => (depth === 0 || depth === 2 || depth === 4) && name === MATRIX_LEGACY_INBOUND_DEDUPE_FILENAME || depth === 5 && name === "openclaw.sqlite", [
|
|
125
124
|
0,
|
|
126
125
|
2,
|
|
127
126
|
4
|
|
128
127
|
]);
|
|
129
|
-
for (const entry of entries) if (entry.name ===
|
|
128
|
+
for (const entry of entries) if (entry.name === MATRIX_LEGACY_INBOUND_DEDUPE_FILENAME) throw new Error(describeRetiredMatrixState(entry.path));
|
|
130
129
|
else sqliteRoots.add(path.dirname(path.dirname(entry.path)));
|
|
131
130
|
const warnings = failedDirs.map(({ path: directory, error }) => `Failed scanning Matrix inbound dedupe sources under ${directory}: ${String(error)}`);
|
|
132
131
|
const isAccountRoot = (root) => root !== matrixRoot;
|
|
133
|
-
const roots = {
|
|
134
|
-
sqliteRoots: [...sqliteRoots].filter(isAccountRoot).toSorted(),
|
|
135
|
-
jsonRoots: [...jsonRoots].filter(isAccountRoot).toSorted()
|
|
136
|
-
};
|
|
132
|
+
const roots = { sqliteRoots: [...sqliteRoots].filter(isAccountRoot).toSorted() };
|
|
137
133
|
return warnings.length === 0 ? {
|
|
138
134
|
status: "complete",
|
|
139
135
|
...roots
|
|
@@ -232,50 +228,8 @@ async function verifyMatrixInboundDedupeSourcesRetired(stateDir) {
|
|
|
232
228
|
} catch (err) {
|
|
233
229
|
warnings.push(`Failed verifying retired Matrix inbound dedupe rows for ${storageRootDir}: ${String(err)}`);
|
|
234
230
|
}
|
|
235
|
-
for (const storageRootDir of remaining.jsonRoots) warnings.push(`Matrix inbound dedupe JSON remains after retirement for ${storageRootDir}`);
|
|
236
231
|
return warnings;
|
|
237
232
|
}
|
|
238
|
-
async function resolveJsonRootAccountId(storageRootDir) {
|
|
239
|
-
for (const filename of [STORAGE_META_FILENAME, `${STORAGE_META_FILENAME}.migrated`]) try {
|
|
240
|
-
const metadata = normalizeMatrixStorageMetadata(JSON.parse(await fs.readFile(path.join(storageRootDir, filename), "utf8")));
|
|
241
|
-
if (metadata?.accountId) return metadata.accountId;
|
|
242
|
-
} catch {}
|
|
243
|
-
return "default";
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Reads one storage root's legacy inbound-dedupe.json markers. Throws on file
|
|
247
|
-
* read errors so a transiently unreadable file is never retired unread, and
|
|
248
|
-
* returns null for malformed content so the caller can archive it explicitly.
|
|
249
|
-
*/
|
|
250
|
-
async function readLegacyInboundDedupeJsonSource(storageRootDir) {
|
|
251
|
-
const jsonPath = path.join(storageRootDir, MATRIX_LEGACY_INBOUND_DEDUPE_FILENAME);
|
|
252
|
-
const raw = await fs.readFile(jsonPath, "utf8");
|
|
253
|
-
let parsed;
|
|
254
|
-
try {
|
|
255
|
-
parsed = JSON.parse(raw);
|
|
256
|
-
} catch {
|
|
257
|
-
return null;
|
|
258
|
-
}
|
|
259
|
-
if (!isRecord(parsed) || parsed.version !== LEGACY_JSON_VERSION || !Array.isArray(parsed.entries)) return null;
|
|
260
|
-
const accountId = await resolveJsonRootAccountId(storageRootDir);
|
|
261
|
-
const markers = [];
|
|
262
|
-
for (const entry of parsed.entries) {
|
|
263
|
-
if (!isRecord(entry) || typeof entry.key !== "string") continue;
|
|
264
|
-
const separator = entry.key.indexOf("|");
|
|
265
|
-
if (separator <= 0) continue;
|
|
266
|
-
const roomId = entry.key.slice(0, separator).trim();
|
|
267
|
-
const eventId = entry.key.slice(separator + 1).trim();
|
|
268
|
-
const ts = normalizeLegacyTimestamp(entry.ts);
|
|
269
|
-
if (!roomId || !eventId || ts === null) continue;
|
|
270
|
-
markers.push({
|
|
271
|
-
accountId,
|
|
272
|
-
roomId,
|
|
273
|
-
eventId,
|
|
274
|
-
ts
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
return markers;
|
|
278
|
-
}
|
|
279
233
|
/**
|
|
280
234
|
* Imports the globally newest legacy markers into the claimable-dedupe store.
|
|
281
235
|
* Never exceeds capacity, never replaces a post-upgrade destination row, and
|
|
@@ -285,7 +239,7 @@ async function readLegacyInboundDedupeJsonSource(storageRootDir) {
|
|
|
285
239
|
*/
|
|
286
240
|
async function importNewestInboundDedupeMarkers(params) {
|
|
287
241
|
const { createPersistentDedupeImportEntry } = await import("openclaw/plugin-sdk/persistent-dedupe");
|
|
288
|
-
const { buildMatrixInboundDedupeEventKey, MATRIX_INBOUND_DEDUPE_STATE_MAX_ENTRIES, MATRIX_INBOUND_DEDUPE_TTL_MS, resolveMatrixInboundDedupeStateNamespace } = await import("./.setup/inbound-dedupe-
|
|
242
|
+
const { buildMatrixInboundDedupeEventKey, MATRIX_INBOUND_DEDUPE_STATE_MAX_ENTRIES, MATRIX_INBOUND_DEDUPE_TTL_MS, resolveMatrixInboundDedupeStateNamespace } = await import("./.setup/inbound-dedupe-C-EBGY0B.mjs");
|
|
289
243
|
const now = params.now ?? Date.now();
|
|
290
244
|
const stateMaxEntries = params.stateMaxEntries ?? MATRIX_INBOUND_DEDUPE_STATE_MAX_ENTRIES;
|
|
291
245
|
const newestByKey = /* @__PURE__ */ new Map();
|
|
@@ -352,7 +306,6 @@ async function importNewestInboundDedupeMarkers(params) {
|
|
|
352
306
|
//#endregion
|
|
353
307
|
//#region extensions/matrix/doctor-contract-api.ts
|
|
354
308
|
const MATRIX_SYNC_CACHE_FILENAME = "bot-storage.json";
|
|
355
|
-
const MATRIX_STORAGE_META_FILENAME = "storage-meta.json";
|
|
356
309
|
async function collectLegacyMatrixCredentialSources(params) {
|
|
357
310
|
const credentialsDir = resolveMatrixCredentialsDir(params.stateDir);
|
|
358
311
|
let entries;
|
|
@@ -367,7 +320,7 @@ async function collectLegacyMatrixCredentialSources(params) {
|
|
|
367
320
|
return left.name.localeCompare(right.name);
|
|
368
321
|
});
|
|
369
322
|
if (files.length === 0) return [];
|
|
370
|
-
const { requiresExplicitMatrixDefaultAccount, resolveMatrixDefaultOrOnlyAccountId } = await import("./.setup/account-selection-
|
|
323
|
+
const { requiresExplicitMatrixDefaultAccount, resolveMatrixDefaultOrOnlyAccountId } = await import("./.setup/account-selection-BDeeqwwR.mjs").then((n) => n.t);
|
|
371
324
|
return files.map((entry) => {
|
|
372
325
|
const namedAccount = /^credentials(?:-([a-z0-9._-]+))?\.json$/iu.exec(entry.name)?.[1];
|
|
373
326
|
return {
|
|
@@ -389,94 +342,16 @@ async function readLegacyMatrixCredentials(source) {
|
|
|
389
342
|
return null;
|
|
390
343
|
}
|
|
391
344
|
}
|
|
392
|
-
async function
|
|
393
|
-
const { entries } = await walkMatrixStateFiles(stateDir, (name, depth) => name ===
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
return null;
|
|
345
|
+
async function* readLegacyMatrixSyncCacheSources(stateDir) {
|
|
346
|
+
const { entries } = await walkMatrixStateFiles(stateDir, (name, depth) => name === MATRIX_SYNC_CACHE_FILENAME && (depth === 2 || depth === 4));
|
|
347
|
+
for (const storageRootDir of entries.map((entry) => path.dirname(entry.path)).toSorted()) {
|
|
348
|
+
const payload = await readLegacyMatrixSyncCacheState(storageRootDir);
|
|
349
|
+
if (payload) yield {
|
|
350
|
+
storageRootDir,
|
|
351
|
+
payload
|
|
352
|
+
};
|
|
401
353
|
}
|
|
402
354
|
}
|
|
403
|
-
async function archiveLegacyMatrixStateFile(params) {
|
|
404
|
-
const warningCount = params.warnings.length;
|
|
405
|
-
await (0, runtime_doctor_migrations_exports.archiveLegacyStateSource)({
|
|
406
|
-
filePath: path.join(params.storageRootDir, params.filename),
|
|
407
|
-
label: params.label,
|
|
408
|
-
changes: params.changes,
|
|
409
|
-
warnings: params.warnings
|
|
410
|
-
});
|
|
411
|
-
if (params.notice && params.warnings.length === warningCount) params.notices?.push(params.notice);
|
|
412
|
-
}
|
|
413
|
-
function defineMatrixLegacyFileMigration(spec) {
|
|
414
|
-
const jsonLabel = spec.jsonLabel ?? spec.label;
|
|
415
|
-
const readSources = async function* (stateDir) {
|
|
416
|
-
for (const storageRootDir of await collectLegacyMatrixStateRoots(stateDir, spec.filename, spec)) {
|
|
417
|
-
const payload = await spec.read(storageRootDir);
|
|
418
|
-
if (payload) yield {
|
|
419
|
-
storageRootDir,
|
|
420
|
-
payload
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
};
|
|
424
|
-
return {
|
|
425
|
-
id: spec.id,
|
|
426
|
-
label: spec.label,
|
|
427
|
-
async detectLegacyState(params) {
|
|
428
|
-
const previews = [];
|
|
429
|
-
for await (const { storageRootDir } of readSources(params.stateDir)) previews.push(`${jsonLabel} JSON can migrate to SQLite: ${storageRootDir}`);
|
|
430
|
-
return previews.length > 0 ? { preview: previews } : null;
|
|
431
|
-
},
|
|
432
|
-
async migrateLegacyState(params) {
|
|
433
|
-
const changes = [];
|
|
434
|
-
const warnings = [];
|
|
435
|
-
const notices = [];
|
|
436
|
-
for await (const source of readSources(params.stateDir)) {
|
|
437
|
-
const store = params.context.openPluginStateKeyedStore(spec.storeOptions(source.storageRootDir));
|
|
438
|
-
const existing = await spec.hasState({
|
|
439
|
-
...source,
|
|
440
|
-
store
|
|
441
|
-
});
|
|
442
|
-
if (!existing) {
|
|
443
|
-
await spec.write({
|
|
444
|
-
...source,
|
|
445
|
-
store
|
|
446
|
-
});
|
|
447
|
-
changes.push(`Migrated ${jsonLabel} JSON to SQLite for ${source.storageRootDir}`);
|
|
448
|
-
}
|
|
449
|
-
await archiveLegacyMatrixStateFile({
|
|
450
|
-
storageRootDir: source.storageRootDir,
|
|
451
|
-
filename: spec.filename,
|
|
452
|
-
label: spec.label,
|
|
453
|
-
changes,
|
|
454
|
-
warnings,
|
|
455
|
-
notices,
|
|
456
|
-
notice: existing ? `Kept existing ${spec.label} in SQLite and archived the legacy source for ${source.storageRootDir}` : void 0
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
return {
|
|
460
|
-
changes,
|
|
461
|
-
warnings,
|
|
462
|
-
...notices.length > 0 ? { notices } : {}
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
const legacyCryptoMigration = defineMatrixLegacyFileMigration({
|
|
468
|
-
id: "matrix-legacy-crypto-migration-json-to-plugin-state",
|
|
469
|
-
label: "Matrix legacy crypto migration",
|
|
470
|
-
filename: MATRIX_LEGACY_CRYPTO_MIGRATION_FILENAME,
|
|
471
|
-
includeMatrixRoot: true,
|
|
472
|
-
read: readLegacyMatrixLegacyCryptoMigrationState,
|
|
473
|
-
storeOptions: openMatrixLegacyCryptoMigrationStoreOptions,
|
|
474
|
-
hasState: hasMatrixLegacyCryptoMigrationStateInStore,
|
|
475
|
-
write: ({ payload, store }) => writeMatrixLegacyCryptoMigrationStateToStore({
|
|
476
|
-
state: payload,
|
|
477
|
-
store
|
|
478
|
-
})
|
|
479
|
-
});
|
|
480
355
|
const stateMigrations = [
|
|
481
356
|
matrixAccountStateSchemaMigration,
|
|
482
357
|
{
|
|
@@ -557,9 +432,11 @@ const stateMigrations = [
|
|
|
557
432
|
id: "matrix-inbound-dedupe-to-claimable-dedupe",
|
|
558
433
|
label: "Matrix inbound dedupe markers",
|
|
559
434
|
async detectLegacyState(params) {
|
|
435
|
+
await collectMatrixInboundDedupeSources(params.stateDir);
|
|
560
436
|
return await hasCompletedMatrixInboundDedupeMigration(params.context, params.env) ? null : { preview: ["Matrix inbound dedupe legacy sources need a one-time migration scan"] };
|
|
561
437
|
},
|
|
562
438
|
async migrateLegacyState(params) {
|
|
439
|
+
const sources = await collectMatrixInboundDedupeSources(params.stateDir);
|
|
563
440
|
const io = {
|
|
564
441
|
context: params.context,
|
|
565
442
|
env: params.env
|
|
@@ -579,7 +456,6 @@ const stateMigrations = [
|
|
|
579
456
|
warnings
|
|
580
457
|
};
|
|
581
458
|
}
|
|
582
|
-
const sources = await collectMatrixInboundDedupeSources(params.stateDir);
|
|
583
459
|
if (sources.status === "incomplete") warnings.push(...sources.warnings);
|
|
584
460
|
const recordCompletionIfClean = async (verifyRetirement = false) => {
|
|
585
461
|
if (warnings.length > 0) return;
|
|
@@ -589,7 +465,7 @@ const stateMigrations = [
|
|
|
589
465
|
}
|
|
590
466
|
try {
|
|
591
467
|
await recordMatrixInboundDedupeMigrationCompletion(params.context, params.env);
|
|
592
|
-
if (sources.sqliteRoots.length
|
|
468
|
+
if (sources.sqliteRoots.length > 0) changes.push(`Recorded Matrix inbound dedupe migration completion (${sources.sqliteRoots.length} SQLite roots scanned)`);
|
|
593
469
|
} catch (err) {
|
|
594
470
|
warnings.push(`Failed recording Matrix inbound dedupe migration completion: ${String(err)}`);
|
|
595
471
|
}
|
|
@@ -604,16 +480,7 @@ const stateMigrations = [
|
|
|
604
480
|
} catch (err) {
|
|
605
481
|
warnings.push(`Failed reading Matrix inbound dedupe rows for ${storageRootDir}: ${String(err)}; left legacy rows in place`);
|
|
606
482
|
}
|
|
607
|
-
|
|
608
|
-
for (const storageRootDir of sources.jsonRoots) try {
|
|
609
|
-
const markers = await readLegacyInboundDedupeJsonSource(storageRootDir);
|
|
610
|
-
if (markers === null) warnings.push(`Matrix inbound dedupe JSON for ${storageRootDir} is malformed; archived without import`);
|
|
611
|
-
else gathered.push(...markers);
|
|
612
|
-
jsonRootsToRetire.push(storageRootDir);
|
|
613
|
-
} catch (err) {
|
|
614
|
-
warnings.push(`Failed reading Matrix inbound dedupe JSON for ${storageRootDir}: ${String(err)}; left legacy file in place`);
|
|
615
|
-
}
|
|
616
|
-
if (sqliteRootsToRetire.length + jsonRootsToRetire.length === 0) {
|
|
483
|
+
if (sqliteRootsToRetire.length === 0) {
|
|
617
484
|
await recordCompletionIfClean();
|
|
618
485
|
return {
|
|
619
486
|
changes,
|
|
@@ -639,13 +506,6 @@ const stateMigrations = [
|
|
|
639
506
|
} catch (err) {
|
|
640
507
|
warnings.push(`Failed retiring Matrix inbound dedupe rows for ${storageRootDir}: ${String(err)}`);
|
|
641
508
|
}
|
|
642
|
-
for (const storageRootDir of jsonRootsToRetire) await archiveLegacyMatrixStateFile({
|
|
643
|
-
storageRootDir,
|
|
644
|
-
filename: MATRIX_LEGACY_INBOUND_DEDUPE_FILENAME,
|
|
645
|
-
label: "Matrix inbound dedupe",
|
|
646
|
-
changes,
|
|
647
|
-
warnings
|
|
648
|
-
});
|
|
649
509
|
await recordCompletionIfClean(true);
|
|
650
510
|
return {
|
|
651
511
|
changes,
|
|
@@ -653,53 +513,39 @@ const stateMigrations = [
|
|
|
653
513
|
};
|
|
654
514
|
}
|
|
655
515
|
},
|
|
656
|
-
|
|
657
|
-
id: "matrix-storage-meta-json-to-plugin-state",
|
|
658
|
-
label: "Matrix storage metadata",
|
|
659
|
-
filename: MATRIX_STORAGE_META_FILENAME,
|
|
660
|
-
read: readLegacyMatrixStorageMetadata,
|
|
661
|
-
storeOptions: openMatrixStorageMetaStoreOptions,
|
|
662
|
-
hasState: hasMatrixStorageMetaStateInStore,
|
|
663
|
-
write: writeMatrixStorageMetaStateToStore
|
|
664
|
-
}),
|
|
665
|
-
defineMatrixLegacyFileMigration({
|
|
516
|
+
{
|
|
666
517
|
id: "matrix-sync-cache-json-to-plugin-state",
|
|
667
518
|
label: "Matrix sync cache",
|
|
668
|
-
filename: MATRIX_SYNC_CACHE_FILENAME,
|
|
669
|
-
read: readLegacyMatrixSyncCacheState,
|
|
670
|
-
storeOptions: openMatrixSyncCacheStoreOptions,
|
|
671
|
-
hasState: hasMatrixSyncCacheStateInStore,
|
|
672
|
-
write: writeMatrixSyncCacheStateToStore
|
|
673
|
-
}),
|
|
674
|
-
defineMatrixLegacyFileMigration({
|
|
675
|
-
id: "matrix-recovery-key-json-to-plugin-state",
|
|
676
|
-
label: "Matrix recovery key",
|
|
677
|
-
jsonLabel: "Matrix recovery-key",
|
|
678
|
-
filename: MATRIX_RECOVERY_KEY_FILENAME,
|
|
679
|
-
read: readLegacyMatrixRecoveryKeyState,
|
|
680
|
-
storeOptions: openMatrixRecoveryKeyStoreOptions,
|
|
681
|
-
hasState: hasMatrixRecoveryKeyStateInStore,
|
|
682
|
-
write: writeMatrixRecoveryKeyStateToStore
|
|
683
|
-
}),
|
|
684
|
-
{
|
|
685
|
-
id: "matrix-legacy-crypto-migration-json-to-plugin-state",
|
|
686
|
-
label: "Matrix legacy crypto state",
|
|
687
519
|
async detectLegacyState(params) {
|
|
688
|
-
const previews =
|
|
689
|
-
for (const storageRootDir of
|
|
520
|
+
const previews = [];
|
|
521
|
+
for await (const { storageRootDir } of readLegacyMatrixSyncCacheSources(params.stateDir)) previews.push(`Matrix sync cache JSON can migrate to SQLite: ${storageRootDir}`);
|
|
690
522
|
return previews.length > 0 ? { preview: previews } : null;
|
|
691
523
|
},
|
|
692
524
|
async migrateLegacyState(params) {
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
525
|
+
const changes = [];
|
|
526
|
+
const warnings = [];
|
|
527
|
+
const notices = [];
|
|
528
|
+
for await (const source of readLegacyMatrixSyncCacheSources(params.stateDir)) {
|
|
529
|
+
const store = params.context.openPluginStateKeyedStore(openMatrixSyncCacheStoreOptions(source.storageRootDir));
|
|
530
|
+
const existing = await hasMatrixSyncCacheStateInStore({
|
|
531
|
+
...source,
|
|
532
|
+
store
|
|
533
|
+
});
|
|
534
|
+
if (!existing) {
|
|
535
|
+
await writeMatrixSyncCacheStateToStore({
|
|
536
|
+
...source,
|
|
537
|
+
store
|
|
538
|
+
});
|
|
539
|
+
changes.push(`Migrated Matrix sync cache JSON to SQLite for ${source.storageRootDir}`);
|
|
540
|
+
}
|
|
541
|
+
const warningCount = warnings.length;
|
|
542
|
+
await (0, runtime_doctor_migrations_exports.archiveLegacyStateSource)({
|
|
543
|
+
filePath: path.join(source.storageRootDir, MATRIX_SYNC_CACHE_FILENAME),
|
|
544
|
+
label: "Matrix sync cache",
|
|
699
545
|
changes,
|
|
700
|
-
notices,
|
|
701
546
|
warnings
|
|
702
547
|
});
|
|
548
|
+
if (existing && warnings.length === warningCount) notices.push(`Kept existing Matrix sync cache in SQLite and archived the legacy source for ${source.storageRootDir}`);
|
|
703
549
|
}
|
|
704
550
|
return {
|
|
705
551
|
changes,
|
package/dist/helper-api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveConfiguredMatrixAccountIds, i as requiresExplicitMatrixDefaultAccount, n as findMatrixAccountEntry, o as resolveMatrixChannelConfig, r as hasImplicitMatrixAccountConfig, s as resolveMatrixDefaultOrOnlyAccountId } from "./.setup/account-selection-
|
|
1
|
+
import { a as resolveConfiguredMatrixAccountIds, i as requiresExplicitMatrixDefaultAccount, n as findMatrixAccountEntry, o as resolveMatrixChannelConfig, r as hasImplicitMatrixAccountConfig, s as resolveMatrixDefaultOrOnlyAccountId } from "./.setup/account-selection-BDeeqwwR.mjs";
|
|
2
2
|
import { n as listMatrixEnvAccountIds, r as resolveMatrixEnvAccountToken, t as getMatrixScopedEnvVarNames } from "./.setup/env-vars-dGqak9dN.mjs";
|
|
3
3
|
import { a as resolveMatrixCredentialsFilename, c as resolveMatrixStateLayoutChildDepth, i as resolveMatrixCredentialsDir, l as sanitizeMatrixPathSegment, n as isMatrixActiveTokenRootDirectory, o as resolveMatrixCredentialsPath, r as resolveMatrixAccountStorageRoot, s as resolveMatrixHomeserverKey, t as hashMatrixAccessToken } from "./.setup/storage-paths-B51JM-pC.mjs";
|
|
4
4
|
export { findMatrixAccountEntry, getMatrixScopedEnvVarNames, hasImplicitMatrixAccountConfig, hashMatrixAccessToken, isMatrixActiveTokenRootDirectory, listMatrixEnvAccountIds, requiresExplicitMatrixDefaultAccount, resolveConfiguredMatrixAccountIds, resolveMatrixAccountStorageRoot, resolveMatrixChannelConfig, resolveMatrixCredentialsDir, resolveMatrixCredentialsFilename, resolveMatrixCredentialsPath, resolveMatrixDefaultOrOnlyAccountId, resolveMatrixEnvAccountToken, resolveMatrixHomeserverKey, resolveMatrixStateLayoutChildDepth, sanitizeMatrixPathSegment };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as registerMatrixCliMetadata } from "./.setup/cli-metadata-
|
|
1
|
+
import { n as registerMatrixCliMetadata } from "./.setup/cli-metadata-CtcjBFhc.mjs";
|
|
2
2
|
import { a as setMatrixRuntimeLifecycle } from "./.setup/runtime-1kn1P6io.mjs";
|
|
3
3
|
import "./runtime-setter-api.js";
|
|
4
4
|
import { registerMatrixSubagentHooks } from "./subagent-hooks-api.js";
|
|
@@ -2,7 +2,7 @@ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
|
2
2
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
4
4
|
//#region extensions/matrix/src/plugin-entry.runtime.ts
|
|
5
|
-
const loadMatrixVerificationRuntime = createLazyRuntimeModule(() => import("./.setup/verification-
|
|
5
|
+
const loadMatrixVerificationRuntime = createLazyRuntimeModule(() => import("./.setup/verification-kMlFYUn0.mjs").then((n) => n.y));
|
|
6
6
|
function sendError(respond, err) {
|
|
7
7
|
respond(false, { error: formatErrorMessage(err) });
|
|
8
8
|
}
|
package/dist/runtime-api.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { i as setMatrixRuntime } from "./.setup/runtime-1kn1P6io.mjs";
|
|
2
|
-
import { a as resolveConfiguredMatrixAccountIds, f as resolveMatrixAccountStringValues, i as requiresExplicitMatrixDefaultAccount, n as findMatrixAccountEntry, o as resolveMatrixChannelConfig, s as resolveMatrixDefaultOrOnlyAccountId } from "./.setup/account-selection-
|
|
2
|
+
import { a as resolveConfiguredMatrixAccountIds, f as resolveMatrixAccountStringValues, i as requiresExplicitMatrixDefaultAccount, n as findMatrixAccountEntry, o as resolveMatrixChannelConfig, s as resolveMatrixDefaultOrOnlyAccountId } from "./.setup/account-selection-BDeeqwwR.mjs";
|
|
3
3
|
import { n as listMatrixEnvAccountIds, r as resolveMatrixEnvAccountToken, t as getMatrixScopedEnvVarNames } from "./.setup/env-vars-dGqak9dN.mjs";
|
|
4
4
|
import { a as resolveMatrixCredentialsFilename, i as resolveMatrixCredentialsDir, l as sanitizeMatrixPathSegment, o as resolveMatrixCredentialsPath, r as resolveMatrixAccountStorageRoot, s as resolveMatrixHomeserverKey, t as hashMatrixAccessToken } from "./.setup/storage-paths-B51JM-pC.mjs";
|
|
5
5
|
import { d as setMatrixThreadBindingMaxAgeBySessionKey, l as setMatrixThreadBindingIdleTimeoutBySessionKey } from "./.setup/thread-bindings-shared-hxKkYC1W.mjs";
|
|
6
|
-
import { n as ensureMatrixSdkInstalled, r as isMatrixSdkAvailable } from "./.setup/deps-
|
|
6
|
+
import { n as ensureMatrixSdkInstalled, r as isMatrixSdkAvailable } from "./.setup/deps-CFNl7tQo.mjs";
|
|
7
7
|
import { chunkTextForOutbound as chunkTextForOutbound$1 } from "openclaw/plugin-sdk/text-chunking";
|
|
8
8
|
import { assertHttpUrlTargetsPrivateNetwork, closeDispatcher, createPinnedDispatcher, resolvePinnedHostnameWithPolicy, ssrfPolicyFromDangerouslyAllowPrivateNetwork } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
9
9
|
import { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
|
10
10
|
import { formatZonedTimestamp } from "openclaw/plugin-sdk/time-runtime";
|
|
11
11
|
//#region extensions/matrix/runtime-api.ts
|
|
12
12
|
function chunkTextForOutbound(text, limit) {
|
|
13
|
-
if (text.length === 0) return [
|
|
13
|
+
if (text.length === 0 || limit <= 0) return [text];
|
|
14
14
|
if (Number.isFinite(limit) && limit > 0 && !Number.isInteger(limit)) return chunkTextForOutbound$1(text, limit);
|
|
15
15
|
const chunks = [];
|
|
16
16
|
let remaining = text;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { i as setMatrixRuntime } from "./.setup/runtime-1kn1P6io.mjs";
|
|
2
|
-
import { t as createMatrixThreadBindingManager } from "./.setup/thread-bindings-
|
|
2
|
+
import { t as createMatrixThreadBindingManager } from "./.setup/thread-bindings-DveHVZqN.mjs";
|
|
3
3
|
export { createMatrixThreadBindingManager, setMatrixRuntime };
|
package/dist/setup-entry.js
CHANGED
|
@@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
var setup_entry_default = defineBundledChannelSetupEntry({
|
|
5
5
|
importMetaUrl: import.meta.url,
|
|
6
6
|
plugin: {
|
|
7
|
-
specifier: fileURLToPath(new URL(".setup/setup-plugin-api-
|
|
7
|
+
specifier: fileURLToPath(new URL(".setup/setup-plugin-api-BRs9bcp4.mjs", import.meta.url).href),
|
|
8
8
|
exportName: "matrixSetupPlugin"
|
|
9
9
|
},
|
|
10
10
|
secrets: {
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as matrixSetupPlugin } from "./.setup/channel.setup-
|
|
1
|
+
import { n as matrixSetupPlugin } from "./.setup/channel.setup-DC2t7_PK.mjs";
|
|
2
2
|
export { matrixSetupPlugin };
|
|
@@ -2,6 +2,101 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.23.0 - 2026-10-02
|
|
6
|
+
|
|
7
|
+
### Highlights
|
|
8
|
+
|
|
9
|
+
- **BREAKING: Python bridge removed:** remove the Python bridge and its compatibility options; migrate to `configureFsSafeNative` / `FS_SAFE_NATIVE_MODE`. ([#815](https://github.com/openclaw/fs-safe/pull/815))
|
|
10
|
+
- **Watch overflow:** fold busy hints so unselected sibling churn beside a missing tree no longer overflows the watch. ([#813](https://github.com/openclaw/fs-safe/pull/813))
|
|
11
|
+
- **Windows exclusive creation:** no longer follows unchanged dangling file symlinks, including standalone creators, unrooted locks and cross-volume copy publication. ([#823](https://github.com/openclaw/fs-safe/pull/823), [#824](https://github.com/openclaw/fs-safe/pull/824))
|
|
12
|
+
- **Faster metadata listings:** reduce path normalization and per-entry allocation when listing Root directory metadata. ([#818](https://github.com/openclaw/fs-safe/pull/818), [#819](https://github.com/openclaw/fs-safe/pull/819))
|
|
13
|
+
|
|
14
|
+
### Fixes
|
|
15
|
+
|
|
16
|
+
- **Windows directory preparation:** retain exact file identities in `ensureAbsoluteDirectory()` so a replaced directory cannot compare equal after large Windows file IDs are rounded to JavaScript numbers. ([#825](https://github.com/openclaw/fs-safe/pull/825))
|
|
17
|
+
- **Windows writable creation:** in native `auto`/`off` mode, `openWritable()`, `append()`, and create-only writes could create a dangling file symlink's missing in-Root target before rejecting the link. Check final leaves before fallback creation; outside-Root targets were already rejected. ([#823](https://github.com/openclaw/fs-safe/pull/823))
|
|
18
|
+
- **Windows symlink creation escape:** unchanged dangling file symlinks could redirect standalone exclusive creation outside the caller-selected directory, including source contents during cross-volume copy publication and records from unrooted fallback locks. Check final leaves before creation, including internal staging files; concurrent replacement remains best-effort. ([#824](https://github.com/openclaw/fs-safe/pull/824))
|
|
19
|
+
- **Atomic writes:** preserve both parent-directory preparation and descriptor-close failures, in operation-first order, for synchronous and asynchronous replacements. ([#820](https://github.com/openclaw/fs-safe/pull/820))
|
|
20
|
+
- **Watch overflow:** fold busy pending hints into guarded subtree reconciliation so unselected sibling churn beside a missing tree no longer exhausts the hint budget. ([#813](https://github.com/openclaw/fs-safe/pull/813))
|
|
21
|
+
- **Native initialization:** lazily load the addon in fs-safe's import context so its housekeeping does not retain the first operation's `AsyncLocalStorage` stores when fs-safe is imported outside caller scopes. ([#797](https://github.com/openclaw/fs-safe/pull/797))
|
|
22
|
+
|
|
23
|
+
### Performance
|
|
24
|
+
|
|
25
|
+
- **Root metadata path assembly:** avoid renormalizing each literal child beneath its canonical directory, cutting 1,000-entry listing time by a further 19–23% and sampled allocations by 33–34% on Linux x64. ([#819](https://github.com/openclaw/fs-safe/pull/819))
|
|
26
|
+
- **Root metadata listings:** construct named metadata once per entry, reducing 1,000-entry listing time by 16% and sampled allocations by 27–28% on Linux x64, with all filesystem and identity checks retained. ([#818](https://github.com/openclaw/fs-safe/pull/818))
|
|
27
|
+
|
|
28
|
+
### Compatibility
|
|
29
|
+
|
|
30
|
+
- **Removed compatibility options:** remove `configureFsSafePython`, `FsSafePythonConfig`, `pythonPath`, and the six Python environment variables; use `configureFsSafeNative`, `FsSafeNativeConfig`, and `FS_SAFE_NATIVE_MODE` (or `OPENCLAW_FS_SAFE_NATIVE_MODE`). The Python variables are now ignored, so a deployment that still sets `FS_SAFE_PYTHON_MODE=require` or `off` runs in `auto` until it sets `FS_SAFE_NATIVE_MODE`. Remove secure-temp `chmodSync`, atomic adapter `chmod`/`chmodSync`, Root `nonBlockingRead`, and ACL `principalSids`; use descriptor-bound permission adapters (`descriptor` for secure-temp, `FileHandle.chmod` / `fchmodSync` for atomic writes), automatic nonblocking read admission, and direct SID classification. Callers passing removed options get TypeScript errors. ([#815](https://github.com/openclaw/fs-safe/pull/815))
|
|
31
|
+
|
|
32
|
+
## 0.22.0 - 2026-10-01
|
|
33
|
+
|
|
34
|
+
### Highlights
|
|
35
|
+
|
|
36
|
+
- **One-way publication:** `retainEntryForPublication` on `advanced` provides no-replace export for POSIX directories, regular files and direct symlinks, plus Windows NTFS files, directories, symbolic links and junctions. ([#776](https://github.com/openclaw/fs-safe/pull/776), [#778](https://github.com/openclaw/fs-safe/pull/778), [#779](https://github.com/openclaw/fs-safe/pull/779))
|
|
37
|
+
- **Windows path hardening:** reject foreign UNC shares and device namespaces before filesystem probes, blocking attacker-chosen SMB lookups, NTLM exposure and stalls. ([#781](https://github.com/openclaw/fs-safe/pull/781), [#784](https://github.com/openclaw/fs-safe/pull/784))
|
|
38
|
+
- **Watch overflow fixes:** Linux watch-retirement echoes no longer overflow unrelated subscriptions; Linux and macOS classify undecodable names, Linux preserves nameless lifecycle events, and macOS cleans up failed startup correctly. ([#782](https://github.com/openclaw/fs-safe/pull/782), [#783](https://github.com/openclaw/fs-safe/pull/783), [#769](https://github.com/openclaw/fs-safe/pull/769))
|
|
39
|
+
|
|
40
|
+
### Features
|
|
41
|
+
|
|
42
|
+
- **One-way publication:** `retainEntryForPublication` retains source and parent identities for native no-replace export on supported local POSIX filesystems and Windows NTFS. It supports directories, regular files and direct symbolic links, plus NTFS junctions; link targets stay opaque, and POSIX relative and dangling targets retain their exact bytes. Commit, indeterminate and close failures remain distinct. Requires caller-exclusive source namespaces, with no source-CAS or automatic rollback guarantee; disposal only closes retained resources and never deletes either location. ([#776](https://github.com/openclaw/fs-safe/pull/776), [#778](https://github.com/openclaw/fs-safe/pull/778), [#779](https://github.com/openclaw/fs-safe/pull/779))
|
|
43
|
+
|
|
44
|
+
### Fixes
|
|
45
|
+
|
|
46
|
+
- **Watch name handling:** ignore undecodable unselected siblings, fail closed for selected tree names on Linux and macOS, and preserve Linux directory lifecycle detail without spurious overflow. ([#783](https://github.com/openclaw/fs-safe/pull/783))
|
|
47
|
+
- **Windows UNC admission:** Root, root-file readers, `pathScope`, `isPathInside`, secret-file writers, sibling-temp output, trash admission, and archive output preparation reject foreign UNC shares and device namespaces before probing them, comparing hosts without Unicode case folding, preventing attacker-chosen SMB lookups, NTLM exposure, and stalls. Existing containment errors are preserved; absolute paths on another share no longer resolve through aliases back into the boundary. ([#781](https://github.com/openclaw/fs-safe/pull/781), [#784](https://github.com/openclaw/fs-safe/pull/784))
|
|
48
|
+
- **Linux watch isolation:** closing or replacing a watch, including after a scan failure, no longer overflows unrelated subscriptions. ([#782](https://github.com/openclaw/fs-safe/pull/782))
|
|
49
|
+
- **macOS watch startup:** clean up rejected FSEvents configuration and failed stream startup with the correct lifecycle calls, keeping the registration available for retry. ([#769](https://github.com/openclaw/fs-safe/pull/769))
|
|
50
|
+
|
|
51
|
+
### Performance
|
|
52
|
+
|
|
53
|
+
- **Bounded temporary-directory cleanup:** avoid a redundant descriptor metadata read for each descendant directory on Linux and macOS, while retaining fresh name identity checks before removal. ([#760](https://github.com/openclaw/fs-safe/pull/760))
|
|
54
|
+
- **Atomic temp cleanup:** use the file identity captured after creation, avoiding an unnecessary metadata lookup and preserving preexisting temporary paths. ([#772](https://github.com/openclaw/fs-safe/pull/772))
|
|
55
|
+
|
|
56
|
+
### Compatibility
|
|
57
|
+
|
|
58
|
+
- Windows now rejects foreign UNC shares and device namespaces before probing them. Absolute paths on another share no longer resolve through aliases back into the boundary; callers that relied on that behavior must pass in-boundary paths. ([#781](https://github.com/openclaw/fs-safe/pull/781), [#784](https://github.com/openclaw/fs-safe/pull/784))
|
|
59
|
+
|
|
60
|
+
## 0.21.3 - 2026-09-30
|
|
61
|
+
|
|
62
|
+
### Highlights
|
|
63
|
+
|
|
64
|
+
- **Watch transient files:** excluded files and atomic-save temp files no longer cause spurious overflow when they disappear between guarded passes. ([#773](https://github.com/openclaw/fs-safe/pull/773))
|
|
65
|
+
- **Faster watch rescans:** unrelated native hints skip rescans, and relevant hints reconcile affected directories, reducing scan work and allocation. ([#774](https://github.com/openclaw/fs-safe/pull/774))
|
|
66
|
+
|
|
67
|
+
### Fixes
|
|
68
|
+
|
|
69
|
+
- **Watch:** no longer reports overflow when an excluded or atomic-save temp file appears and disappears between guarded passes under the same observed parent directory. ([#773](https://github.com/openclaw/fs-safe/pull/773))
|
|
70
|
+
- **Windows removal:** nonrecursive `Root.remove()` reports `not-empty` for a nonempty directory in required native mode, including with `force: true`, instead of `not-removable`. ([#771](https://github.com/openclaw/fs-safe/pull/771))
|
|
71
|
+
- **Copy and staging failures:** preserve publication callback errors with unreadable metadata, retain uncertain native rename outcomes, and prevent repeated or reentrant cleanup from reusing consumed descriptors. ([#763](https://github.com/openclaw/fs-safe/pull/763))
|
|
72
|
+
|
|
73
|
+
### Performance
|
|
74
|
+
|
|
75
|
+
- **Watch:** skip guarded unrelated native hints and reconcile affected directories, reducing a 502-file memory-watch fixture from 513 to 55 visits and 8.16 MB to 1.33 MB sampled allocation per relevant event pass; unrelated detailed hints at two edits/second no longer trigger 120 full scans/minute, while periodic and uncertain-event reconciliation remain full. ([#774](https://github.com/openclaw/fs-safe/pull/774))
|
|
76
|
+
- **Linux fallback resolution:** reuse the file type from each component's checked descriptor observation, avoiding a duplicate metadata read while retaining fresh identity, symlink-target, and mount-policy checks. ([#757](https://github.com/openclaw/fs-safe/pull/757))
|
|
77
|
+
- **Native parent validation:** reuse the retained descriptor's captured identity during ordinary POSIX policy checks, avoiding a duplicate metadata read while keeping the final pathname inspection fresh. ([#735](https://github.com/openclaw/fs-safe/pull/735))
|
|
78
|
+
|
|
79
|
+
## 0.21.2 - 2026-09-28
|
|
80
|
+
|
|
81
|
+
### Highlights
|
|
82
|
+
|
|
83
|
+
- **`require` mode confines mutations under hostile concurrency:** with `FS_SAFE_NATIVE_MODE=require` (or `configureFsSafeNative({ mode: "require" })`), remove, recursive remove, `mkdir`, writable-open creation and overwrite `move` now run through retained, identity-checked native parents: descriptor-relative `unlinkat`, `mkdirat` and `renameat2` on POSIX, and handle-relative operations on Windows. An adversarial race fuzzer observed no outside or denied-path effects across about 2.8 million racing calls on Linux (with and without `openat2`), macOS and Windows. `auto` keeps its documented best-effort paths and performance. See the [operation/platform matrix](docs/security-model.md#native-root-mutation-capabilities). ([#744](https://github.com/openclaw/fs-safe/pull/744), [#751](https://github.com/openclaw/fs-safe/pull/751), [#750](https://github.com/openclaw/fs-safe/pull/750), [#752](https://github.com/openclaw/fs-safe/pull/752))
|
|
84
|
+
- **Watch on macOS:** entry scopes use identity-checked kqueue descriptors instead of recursive FSEvents streams, ending overflow storms for shallow ancestor scopes above busy trees. ([#753](https://github.com/openclaw/fs-safe/pull/753))
|
|
85
|
+
- **Faster watch scans:** watch readiness and reconciliation are 27–34% faster on large trees. ([#747](https://github.com/openclaw/fs-safe/pull/747))
|
|
86
|
+
|
|
87
|
+
### Fixes
|
|
88
|
+
|
|
89
|
+
- **Watch cancellation:** a subscription's `signal` closes it even when another abort listener stops event propagation. ([#738](https://github.com/openclaw/fs-safe/pull/738))
|
|
90
|
+
- **Walk cancellation:** walks stop without yielding the current entry when a synchronous filter aborts the signal. ([#739](https://github.com/openclaw/fs-safe/pull/739))
|
|
91
|
+
- **Writes with `mkdir: false`:** the JavaScript fallback writes through existing in-root parent aliases using the same guarded walk, instead of rejecting them. ([#740](https://github.com/openclaw/fs-safe/pull/740))
|
|
92
|
+
- **Descriptor exhaustion:** native writes that fail with `EMFILE`/`ENFILE` report `helper-failed` with the exhaustion code, the indeterminate publication outcome and the preserved stage, instead of a misleading path error. ([#742](https://github.com/openclaw/fs-safe/pull/742))
|
|
93
|
+
- **Walk memory:** `walkDirectory()` and `walkDirectorySync()` stop reading a directory once `maxEntries` is reached instead of enumerating it completely first. `Root.walk()` sorted mode stays deterministic. ([#743](https://github.com/openclaw/fs-safe/pull/743))
|
|
94
|
+
|
|
95
|
+
### Compatibility
|
|
96
|
+
|
|
97
|
+
- In `require` mode, the operations above now reject with `helper-unavailable` where no confining native primitive exists, instead of silently falling back to JavaScript. Examples are recursive removal on Linux without `openat2` and recursive directory removal on Windows. Use `auto` for the best-effort fallback. These `require`-mode mutations also do more identity-checked work and are slower than before, while `auto` is unchanged. ([#744](https://github.com/openclaw/fs-safe/pull/744), [#751](https://github.com/openclaw/fs-safe/pull/751), [#750](https://github.com/openclaw/fs-safe/pull/750))
|
|
98
|
+
- Create-only writes to an existing directory report `already-exists` in every implementation (previously `not-file` on some Windows paths). With `mutationSymlinks` omitted, Windows native and legacy JavaScript writes still differ for final links and parent junctions; set `mutationSymlinks: "reject"` for uniform behavior. ([#745](https://github.com/openclaw/fs-safe/pull/745))
|
|
99
|
+
|
|
5
100
|
## 0.21.1 - 2026-09-27
|
|
6
101
|
|
|
7
102
|
### Fixes
|