@openclaw/signal 2026.9.6 → 2026.9.7
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/assets/icon.png +0 -0
- package/dist/.setup/{accounts-BV6tDOTc.mjs → accounts-DMtj2E-4.mjs} +6 -35
- package/dist/.setup/api-DEB0Obj8.mjs +16 -0
- package/dist/.setup/{api-CGh4eWR8.mjs → api-DmCb6e7E.mjs} +10 -10
- package/dist/.setup/{approval-auth-BBI9BTRm.mjs → approval-auth-CszS7gwf.mjs} +7 -13
- package/dist/.setup/{approval-handler.runtime-C3vN5OWd.mjs → approval-handler.runtime-D9ofZcZW.mjs} +10 -29
- package/dist/.setup/{approval-reactions-DDQvPP_z.mjs → approval-reactions-BKkjIAoi.mjs} +25 -36
- package/dist/.setup/{channel-DhzTcFsK.mjs → channel-DrUxv5cf.mjs} +567 -136
- package/dist/.setup/{client-BseAt7F7.mjs → client-AXcDteBZ.mjs} +63 -152
- package/dist/.setup/client-adapter-c_O1ouxZ.mjs +30 -0
- package/dist/.setup/{config-schema-aQwwMGUj.mjs → config-schema-DvxZ18SD.mjs} +3 -13
- package/dist/.setup/{doctor-contract-api-Rbq_sRTI.mjs → doctor-contract-api-Db9V9gsY.mjs} +212 -91
- package/dist/.setup/{identity-YXPmgFMu.mjs → identity-B3JyPqGO.mjs} +2 -6
- package/dist/.setup/{install-signal-cli-BDbzFcU2.mjs → install-signal-cli-ChvjzM6X.mjs} +0 -4
- package/dist/.setup/legacy-transport-QIpaMNST.mjs +18 -0
- package/dist/.setup/{monitor-Dnz6Ygz5.mjs → monitor-BfwQr78f.mjs} +95 -124
- package/dist/.setup/{probe-DXT2eLnw.mjs → probe-BYLzra6D.mjs} +9 -9
- package/dist/.setup/{reaction-runtime-api-BnQGHcrB.mjs → reaction-runtime-api-DDi5x2wC.mjs} +3 -17
- package/dist/.setup/{question-reactions-C8cSEjVf.mjs → reaction-targets-CEdyjtrC.mjs} +11 -8
- package/dist/.setup/{rpc-context-CwwADZ1b.mjs → rpc-context-D26RxFIm.mjs} +1 -1
- package/dist/.setup/runtime-8sxUF217.mjs +8 -0
- package/dist/.setup/{send-B78M_eFp.mjs → send-DEjrbpIC.mjs} +25 -55
- package/dist/.setup/{channel.runtime-CG79z_Vy.mjs → setup-surface-Drt-4t3R.mjs} +4 -6
- package/dist/.setup/transport-detection-BVUDE42e.mjs +25 -0
- package/dist/.setup/{transport-policy-5VSnj5ma.mjs → transport-policy-B6C_LogW.mjs} +19 -1
- package/dist/.setup/transport-probes.runtime-DwXEHnXr.mjs +2 -0
- package/dist/api.js +10 -10
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/contract-api.js +2 -2
- package/dist/doctor-contract-api.js +1 -1
- package/dist/reaction-runtime-api.js +1 -1
- package/dist/runtime-api.js +2 -19
- package/dist/setup-entry.js +1 -1
- package/node_modules/@openclaw/fs-safe/CHANGELOG.md +102 -0
- package/node_modules/@openclaw/fs-safe/README.md +24 -6
- package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +6 -1
- package/node_modules/@openclaw/fs-safe/dist/advanced.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/archive-durability.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/archive-merge.js +1 -2
- package/node_modules/@openclaw/fs-safe/dist/archive-plan.d.ts +2 -7
- package/node_modules/@openclaw/fs-safe/dist/archive-read.js +9 -18
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts +1 -2
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.js +3 -3
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-directory.js +4 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-entry.d.ts +11 -11
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-entry.js +3 -35
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-integrity.d.ts +2 -2
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-integrity.js +2 -12
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-loader.d.ts +7 -3
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-loader.js +13 -10
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-manifest.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-preflight.d.ts +2 -3
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-preflight.js +16 -8
- package/node_modules/@openclaw/fs-safe/dist/archive.d.ts +6 -3
- package/node_modules/@openclaw/fs-safe/dist/archive.js +22 -19
- package/node_modules/@openclaw/fs-safe/dist/atomic.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-publication.d.ts +1 -3
- package/node_modules/@openclaw/fs-safe/dist/copy-publication.js +2 -6
- package/node_modules/@openclaw/fs-safe/dist/deny-mutation-match.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/deny-mutation-match.js +71 -0
- package/node_modules/@openclaw/fs-safe/dist/deny-mutations.js +4 -3
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +0 -3
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.d.ts +20 -2
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.js +77 -1
- package/node_modules/@openclaw/fs-safe/dist/directory-receipt.js +5 -7
- package/node_modules/@openclaw/fs-safe/dist/effective-uid.js +1 -4
- package/node_modules/@openclaw/fs-safe/dist/errors.d.ts +3 -1
- package/node_modules/@openclaw/fs-safe/dist/errors.js +3 -2
- package/node_modules/@openclaw/fs-safe/dist/file-identity.js +10 -2
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-acquisition.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-admission.js +5 -1
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-held.d.ts +4 -11
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-held.js +1 -4
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-io.d.ts +3 -6
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-io.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-options.d.ts +2 -10
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root.d.ts +2 -4
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.d.ts +3 -7
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.js +7 -10
- package/node_modules/@openclaw/fs-safe/dist/file-store-prune.js +7 -6
- package/node_modules/@openclaw/fs-safe/dist/file-store.d.ts +4 -7
- package/node_modules/@openclaw/fs-safe/dist/file-store.js +19 -21
- package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +23 -31
- package/node_modules/@openclaw/fs-safe/dist/guest.js +21 -12
- package/node_modules/@openclaw/fs-safe/dist/json-document-store.d.ts +4 -9
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.d.ts +1 -5
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue.js +2 -7
- package/node_modules/@openclaw/fs-safe/dist/local-file-access.js +2 -5
- package/node_modules/@openclaw/fs-safe/dist/local-file-descriptor.d.ts +2 -5
- package/node_modules/@openclaw/fs-safe/dist/local-roots.d.ts +2 -7
- package/node_modules/@openclaw/fs-safe/dist/move-path-cleanup.js +4 -4
- package/node_modules/@openclaw/fs-safe/dist/mutation-authority.js +5 -0
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +51 -14
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +8 -2
- package/node_modules/@openclaw/fs-safe/dist/native-staged-symlink.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/native-staged-symlink.js +303 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl-batch-worker.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl-batch-worker.js +54 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl-batch.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl-batch.js +64 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/path.js +17 -1
- package/node_modules/@openclaw/fs-safe/dist/permission-exec.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/permission-exec.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/permissions-public.d.ts +3 -1
- package/node_modules/@openclaw/fs-safe/dist/permissions-public.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts +3 -6
- package/node_modules/@openclaw/fs-safe/dist/permissions.d.ts +3 -10
- package/node_modules/@openclaw/fs-safe/dist/permissions.js +0 -1
- package/node_modules/@openclaw/fs-safe/dist/pinned-mutation-admission.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/pinned-mutation-admission.js +4 -2
- package/node_modules/@openclaw/fs-safe/dist/pinned-mutation-shared-route.d.ts +2 -8
- package/node_modules/@openclaw/fs-safe/dist/pinned-open.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/pinned-open.js +2 -3
- package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +4 -0
- package/node_modules/@openclaw/fs-safe/dist/read-opened-file.d.ts +2 -5
- package/node_modules/@openclaw/fs-safe/dist/regular-file.js +3 -3
- package/node_modules/@openclaw/fs-safe/dist/replace-directory.js +5 -17
- package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.js +36 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts +4 -10
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.js +66 -38
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts +7 -11
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +10 -2
- package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.js +123 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-mutation.d.ts +26 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-mutation.js +47 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts +2 -2
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.js +16 -4
- package/node_modules/@openclaw/fs-safe/dist/replace-file-types.d.ts +55 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file.d.ts +3 -55
- package/node_modules/@openclaw/fs-safe/dist/replace-file.js +31 -11
- package/node_modules/@openclaw/fs-safe/dist/retained-directory-replacement.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/retained-directory-replacement.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/retained-file-types.d.ts +50 -0
- package/node_modules/@openclaw/fs-safe/dist/retained-file-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/retained-file.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/retained-file.js +121 -0
- package/node_modules/@openclaw/fs-safe/dist/root-context.js +3 -2
- package/node_modules/@openclaw/fs-safe/dist/root-directory-entry.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-entry.js +28 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.d.ts +9 -1
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +88 -37
- package/node_modules/@openclaw/fs-safe/dist/root-file-final-admission.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/root-file-final-admission.js +1 -6
- package/node_modules/@openclaw/fs-safe/dist/root-file.js +2 -5
- package/node_modules/@openclaw/fs-safe/dist/root-handle-context.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root-handle-context.js +12 -0
- package/node_modules/@openclaw/fs-safe/dist/root-impl.d.ts +3 -3
- package/node_modules/@openclaw/fs-safe/dist/root-impl.js +8 -5
- package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.d.ts +2 -7
- package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.js +3 -3
- package/node_modules/@openclaw/fs-safe/dist/root-observed-path.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/root-observed-path.js +0 -3
- package/node_modules/@openclaw/fs-safe/dist/root-path-observation.d.ts +4 -11
- package/node_modules/@openclaw/fs-safe/dist/root-path.js +7 -10
- package/node_modules/@openclaw/fs-safe/dist/root-paths.d.ts +2 -6
- package/node_modules/@openclaw/fs-safe/dist/root-remove-identity.d.ts +1 -3
- package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts +19 -12
- package/node_modules/@openclaw/fs-safe/dist/root-walk.js +56 -20
- package/node_modules/@openclaw/fs-safe/dist/root-write-admission.js +1 -6
- package/node_modules/@openclaw/fs-safe/dist/root-write-complete-parent.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-complete-parent.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.js +8 -2
- package/node_modules/@openclaw/fs-safe/dist/secret-file.d.ts +6 -2
- package/node_modules/@openclaw/fs-safe/dist/secret-file.js +12 -16
- package/node_modules/@openclaw/fs-safe/dist/secret-read-policy.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/secure-file-windows.js +5 -14
- package/node_modules/@openclaw/fs-safe/dist/secure-file.js +3 -2
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.js +2 -7
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.js +4 -4
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-admission-parser.d.ts +1 -2
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-handle.d.ts +2 -8
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-policy.d.ts +2 -7
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts +2 -2
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +11 -12
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-stale-admission.d.ts +1 -5
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock.js +9 -7
- package/node_modules/@openclaw/fs-safe/dist/staged-symlink-types.d.ts +39 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-symlink-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/stat-observation.js +3 -10
- package/node_modules/@openclaw/fs-safe/dist/strict-file-identity.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/strict-file-identity.js +6 -6
- package/node_modules/@openclaw/fs-safe/dist/symlink-parents.js +58 -7
- package/node_modules/@openclaw/fs-safe/dist/temp-target.js +8 -10
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-admission.js +28 -33
- 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 +16 -17
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-descriptor.js +1 -2
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.js +4 -9
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-ownership.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-ownership.js +52 -0
- package/node_modules/@openclaw/fs-safe/dist/test-hooks.d.ts +5 -1
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts +2 -1
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/trash.js +27 -1
- package/node_modules/@openclaw/fs-safe/dist/walk.d.ts +2 -5
- package/node_modules/@openclaw/fs-safe/dist/watch-alias.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-alias.js +88 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.js +93 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-native.d.ts +36 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-native.js +73 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.d.ts +28 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.js +300 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-stream.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-stream.js +32 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-types.d.ts +60 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/watch.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/watch.js +530 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-owner.d.ts +3 -7
- package/node_modules/@openclaw/fs-safe/dist/windows-owner.js +0 -1
- package/node_modules/@openclaw/fs-safe/dist/windows-security-bridge.cs +6 -6
- package/node_modules/@openclaw/fs-safe/dist/windows-security-bridge.ps1 +78 -3
- package/node_modules/@openclaw/fs-safe/dist/windows-security-command.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-security-command.js +66 -15
- package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.js +6 -2
- package/node_modules/@openclaw/fs-safe/docs/advanced.md +4 -2
- package/node_modules/@openclaw/fs-safe/docs/archive.md +16 -0
- package/node_modules/@openclaw/fs-safe/docs/atomic.md +93 -3
- package/node_modules/@openclaw/fs-safe/docs/contributing.md +102 -4
- package/node_modules/@openclaw/fs-safe/docs/copy.md +2 -0
- package/node_modules/@openclaw/fs-safe/docs/durability.md +7 -0
- package/node_modules/@openclaw/fs-safe/docs/file-store.md +5 -0
- package/node_modules/@openclaw/fs-safe/docs/guest.md +7 -1
- package/node_modules/@openclaw/fs-safe/docs/index.md +1 -0
- package/node_modules/@openclaw/fs-safe/docs/install.md +30 -0
- package/node_modules/@openclaw/fs-safe/docs/native-helper.md +20 -4
- package/node_modules/@openclaw/fs-safe/docs/native.md +63 -1
- package/node_modules/@openclaw/fs-safe/docs/permissions.md +66 -0
- package/node_modules/@openclaw/fs-safe/docs/public-api.md +30 -3
- package/node_modules/@openclaw/fs-safe/docs/retained-file.md +115 -0
- package/node_modules/@openclaw/fs-safe/docs/root.md +35 -9
- package/node_modules/@openclaw/fs-safe/docs/secret-file.md +19 -0
- package/node_modules/@openclaw/fs-safe/docs/security-model.md +4 -1
- package/node_modules/@openclaw/fs-safe/docs/sidecar-lock.md +5 -1
- package/node_modules/@openclaw/fs-safe/docs/staged-symlink.md +124 -0
- package/node_modules/@openclaw/fs-safe/docs/store.md +3 -1
- package/node_modules/@openclaw/fs-safe/docs/temp.md +24 -4
- package/node_modules/@openclaw/fs-safe/docs/testing.md +210 -0
- package/node_modules/@openclaw/fs-safe/docs/types.md +6 -0
- package/node_modules/@openclaw/fs-safe/docs/walk.md +34 -1
- package/node_modules/@openclaw/fs-safe/docs/watch.md +251 -0
- package/node_modules/@openclaw/fs-safe/docs/writing.md +21 -0
- package/node_modules/@openclaw/fs-safe/package.json +13 -9
- 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/package.json +5 -5
- package/dist/.setup/api-B9-B1L7Q.mjs +0 -17
- package/dist/.setup/client-adapter-dvFa47YL.mjs +0 -63
- package/dist/.setup/rolldown-runtime-8H4AJuhK.mjs +0 -14
- package/dist/.setup/send.runtime-CLnCWvrM.mjs +0 -2
- package/dist/.setup/transport-detection-CoiRl7Gx.mjs +0 -576
- package/dist/.setup/transport-detection.runtime-Tlhuv3T_.mjs +0 -2
- package/dist/.setup/transport-probes.runtime-WprAyBbL.mjs +0 -2
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-owner.d.ts +0 -20
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-owner.js +0 -78
|
@@ -70,11 +70,6 @@ function snapshotDirectoryMetadata(stat, identity) {
|
|
|
70
70
|
export function directoryReceiptAuthority(receipt) {
|
|
71
71
|
return authorities.get(receipt) ?? snapshotDirectoryReceipt(receipt);
|
|
72
72
|
}
|
|
73
|
-
function rememberReceipt(receipt, authority) {
|
|
74
|
-
authorities.set(receipt, authority);
|
|
75
|
-
identities.set(receipt.identity, authority);
|
|
76
|
-
return receipt;
|
|
77
|
-
}
|
|
78
73
|
export function ownDirectoryReceipt(receipt) {
|
|
79
74
|
return receiptFromAuthority(snapshotDirectoryReceipt(receipt));
|
|
80
75
|
}
|
|
@@ -83,11 +78,14 @@ export function copyRetainedDirectoryReceipt(receipt) {
|
|
|
83
78
|
return receiptFromAuthority(authority);
|
|
84
79
|
}
|
|
85
80
|
function receiptFromAuthority(authority) {
|
|
86
|
-
|
|
81
|
+
const receipt = {
|
|
87
82
|
path: authority.path,
|
|
88
83
|
realPath: authority.realPath,
|
|
89
84
|
identity: Object.assign(Object.create(fs.Stats.prototype), authority.metadata),
|
|
90
|
-
}
|
|
85
|
+
};
|
|
86
|
+
authorities.set(receipt, authority);
|
|
87
|
+
identities.set(receipt.identity, authority);
|
|
88
|
+
return receipt;
|
|
91
89
|
}
|
|
92
90
|
// The caller already admitted the exact observation and its paths.
|
|
93
91
|
export function createDirectoryReceiptFromIdentity(pathname, realPath, exactStat) {
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
function isValidUid(value) {
|
|
2
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
3
|
-
}
|
|
4
1
|
function unavailable(cause) {
|
|
5
2
|
return new Error("Effective user identity is unavailable.", {
|
|
6
3
|
...(cause === undefined ? {} : { cause }),
|
|
@@ -18,7 +15,7 @@ export function resolveEffectiveUid() {
|
|
|
18
15
|
catch (cause) {
|
|
19
16
|
throw unavailable(cause);
|
|
20
17
|
}
|
|
21
|
-
if (!
|
|
18
|
+
if (!(typeof uid === "number" && Number.isSafeInteger(uid) && uid >= 0)) {
|
|
22
19
|
throw unavailable();
|
|
23
20
|
}
|
|
24
21
|
return uid;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export type FsSafeErrorCode = "already-exists" | "denied-path" | "device-path" | "hardlink" | "
|
|
1
|
+
export type FsSafeErrorCode = (typeof OPERATIONAL_CODE_VALUES)[number] | "already-exists" | "denied-path" | "device-path" | "hardlink" | "invalid-path" | "insecure-permissions" | "not-file" | "not-owned" | "outside-workspace" | "path-alias" | "path-mismatch" | "secret-exists" | "store-reentrant-update" | "symlink" | "too-large";
|
|
2
2
|
export type FsSafeErrorCategory = "policy" | "operational";
|
|
3
3
|
export type FsSafeErrorDetails = Readonly<Record<string, unknown>>;
|
|
4
|
+
declare const OPERATIONAL_CODE_VALUES: readonly ["helper-failed", "helper-unavailable", "not-empty", "not-found", "not-removable", "permission-unverified", "read-failed", "timeout", "unsupported-platform"];
|
|
4
5
|
export declare function categorizeFsSafeError(code: FsSafeErrorCode): FsSafeErrorCategory;
|
|
5
6
|
export declare class FsSafeError extends Error {
|
|
6
7
|
readonly code: FsSafeErrorCode;
|
|
@@ -11,3 +12,4 @@ export declare class FsSafeError extends Error {
|
|
|
11
12
|
details?: FsSafeErrorDetails;
|
|
12
13
|
});
|
|
13
14
|
}
|
|
15
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const OPERATIONAL_CODE_VALUES = [
|
|
2
2
|
"helper-failed",
|
|
3
3
|
"helper-unavailable",
|
|
4
4
|
"not-empty",
|
|
@@ -8,7 +8,8 @@ const OPERATIONAL_CODES = new Set([
|
|
|
8
8
|
"read-failed",
|
|
9
9
|
"timeout",
|
|
10
10
|
"unsupported-platform",
|
|
11
|
-
]
|
|
11
|
+
];
|
|
12
|
+
const OPERATIONAL_CODES = new Set(OPERATIONAL_CODE_VALUES);
|
|
12
13
|
export function categorizeFsSafeError(code) {
|
|
13
14
|
return OPERATIONAL_CODES.has(code) ? "operational" : "policy";
|
|
14
15
|
}
|
|
@@ -22,9 +22,17 @@ export function sameFileIdentity(left, right, platform = process.platform) {
|
|
|
22
22
|
return (!isStatValueProvablyDifferent(left.dev, right.dev, platform) &&
|
|
23
23
|
!isStatValueProvablyDifferent(left.ino, right.ino, platform));
|
|
24
24
|
}
|
|
25
|
+
function sameCleanupStatValue(left, right) {
|
|
26
|
+
// Converting an unsafe number to bigint cannot recover an already rounded ID.
|
|
27
|
+
if (typeof left === "number" && !Number.isSafeInteger(left))
|
|
28
|
+
return false;
|
|
29
|
+
if (typeof right === "number" && !Number.isSafeInteger(right))
|
|
30
|
+
return false;
|
|
31
|
+
return sameStatValue(left, right);
|
|
32
|
+
}
|
|
25
33
|
export function sameFileIdentityForCleanup(left, right, platform = process.platform) {
|
|
26
34
|
if (platform !== "win32") {
|
|
27
|
-
return
|
|
35
|
+
return sameCleanupStatValue(left.dev, right.dev) && sameCleanupStatValue(left.ino, right.ino);
|
|
28
36
|
}
|
|
29
37
|
// A zero Windows device or inode is unknown, not proof that a pathname still
|
|
30
38
|
// names the object we created. Cleanup must fail closed rather than delete a
|
|
@@ -44,5 +52,5 @@ export function sameFileIdentityForCleanup(left, right, platform = process.platf
|
|
|
44
52
|
const rightIno = right.ino;
|
|
45
53
|
if (isZero(rightIno))
|
|
46
54
|
return false;
|
|
47
|
-
return
|
|
55
|
+
return sameCleanupStatValue(leftDev, rightDev) && sameCleanupStatValue(leftIno, rightIno);
|
|
48
56
|
}
|
|
@@ -66,7 +66,7 @@ export class SyncLockAcquisition {
|
|
|
66
66
|
}
|
|
67
67
|
catch (waitError) {
|
|
68
68
|
// Exhausted backoff must preserve the filesystem denial diagnosis.
|
|
69
|
-
if (waitError
|
|
69
|
+
if (waitError?.code === "file_lock_timeout")
|
|
70
70
|
throw error;
|
|
71
71
|
throw waitError;
|
|
72
72
|
}
|
|
@@ -30,7 +30,11 @@ export function defaultSyncShouldReclaim(snapshot, staleMs, nowMs) {
|
|
|
30
30
|
const createdAtMs = sidecarLockPayloadCreatedAtMs(snapshot.payload);
|
|
31
31
|
if (createdAtMs !== null)
|
|
32
32
|
return nowMs - createdAtMs > staleMs;
|
|
33
|
-
|
|
33
|
+
if (!snapshot.stat)
|
|
34
|
+
return true;
|
|
35
|
+
const mtimeMs = "mtimeNs" in snapshot.stat
|
|
36
|
+
? Number(snapshot.stat.mtimeNs) / 1e6 : snapshot.stat.mtimeMs;
|
|
37
|
+
return nowMs - mtimeMs > staleMs;
|
|
34
38
|
}
|
|
35
39
|
export function syncReclaimGuardExists(reclaimGuardPath) {
|
|
36
40
|
try {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { type SyncHeldLock } from "./file-lock-sync-admission.js";
|
|
2
|
+
import type { SidecarLockOptionFields } from "./sidecar-lock-types.js";
|
|
1
3
|
import type { FileLockSyncHandle } from "./file-lock-sync.js";
|
|
2
|
-
import { type SidecarLockSnapshot } from "./sidecar-lock-reclaim.js";
|
|
3
4
|
import { type FileLockSyncRootAuthority, type FileLockSyncRootPath } from "./file-lock-sync-root.js";
|
|
4
5
|
import { type FileLockSyncRootFileReceipt, type FileLockSyncRootSnapshot } from "./file-lock-sync-root-io.js";
|
|
5
6
|
type RootSyncHeldLockReleaseState = "active" | "releasing" | "exit-cleaning" | "released";
|
|
@@ -7,22 +8,14 @@ type RootSyncHeldLockHandleDisposition = {
|
|
|
7
8
|
held: RootSyncHeldLock;
|
|
8
9
|
released: boolean;
|
|
9
10
|
};
|
|
10
|
-
export type RootSyncHeldLock = {
|
|
11
|
+
export type RootSyncHeldLock = SidecarLockOptionFields<SyncHeldLock & {
|
|
11
12
|
deferredExitReleases?: Set<RootSyncHeldLockHandleDisposition>;
|
|
12
|
-
fd: number | undefined;
|
|
13
|
-
lockPath: string;
|
|
14
|
-
normalizedTargetPath: string;
|
|
15
|
-
parsePayload?: (raw: string) => unknown;
|
|
16
|
-
refCount: number;
|
|
17
|
-
reentrantOwner?: string;
|
|
18
13
|
releaseState: RootSyncHeldLockReleaseState;
|
|
19
14
|
revision: number;
|
|
20
15
|
rootAuthority: FileLockSyncRootAuthority;
|
|
21
16
|
rootPath: FileLockSyncRootPath;
|
|
22
17
|
rootReceipt: FileLockSyncRootFileReceipt;
|
|
23
|
-
|
|
24
|
-
timer?: NodeJS.Timeout;
|
|
25
|
-
};
|
|
18
|
+
}>;
|
|
26
19
|
export declare function readRootSidecarSnapshotSync(rootPath: FileLockSyncRootPath, parsePayload?: (raw: string) => unknown, onOpenFailure?: (error: unknown) => void, expectedReceipt?: FileLockSyncRootFileReceipt): FileLockSyncRootSnapshot | null;
|
|
27
20
|
export declare function getRootSyncHeldLocks(): Map<string, RootSyncHeldLock>;
|
|
28
21
|
export declare function ensureRootSyncExitCleanupRegistered(): void;
|
|
@@ -53,9 +53,6 @@ export function getRootSyncHeldLocks() {
|
|
|
53
53
|
}
|
|
54
54
|
return globalWithState[ROOT_SYNC_HELD_LOCKS_KEY];
|
|
55
55
|
}
|
|
56
|
-
function existingRootSyncHeldLocks() {
|
|
57
|
-
return globalThis[ROOT_SYNC_HELD_LOCKS_KEY];
|
|
58
|
-
}
|
|
59
56
|
function reactivateExactHeldLock(heldLocks, held, restoreConsumedReference) {
|
|
60
57
|
if (heldLocks.get(held.normalizedTargetPath) !== held || held.releaseState === "released") {
|
|
61
58
|
return false;
|
|
@@ -123,7 +120,7 @@ function releaseAllRootSyncHeldLocks() {
|
|
|
123
120
|
try {
|
|
124
121
|
// A newListener callback can invoke the candidate handler before
|
|
125
122
|
// registration succeeds. Do not create acquisition state in that window.
|
|
126
|
-
const heldLocks =
|
|
123
|
+
const heldLocks = globalThis[ROOT_SYNC_HELD_LOCKS_KEY];
|
|
127
124
|
if (!heldLocks)
|
|
128
125
|
return;
|
|
129
126
|
getSyncLockAdmissions().clear();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type BigIntStats
|
|
1
|
+
import { type BigIntStats } from "node:fs";
|
|
2
2
|
import type { RootDefaults } from "./root-options.js";
|
|
3
3
|
import { type FileLockSyncRootPath } from "./file-lock-sync-root.js";
|
|
4
4
|
export type ExactIdentity = Readonly<{
|
|
@@ -14,15 +14,12 @@ export type FileLockSyncRootFileReceipt = Readonly<{
|
|
|
14
14
|
identity: ExactIdentity;
|
|
15
15
|
parent: DirectoryReceipt;
|
|
16
16
|
}>;
|
|
17
|
-
export type FileLockSyncRootDirectoryReceipt =
|
|
18
|
-
identity: ExactIdentity;
|
|
19
|
-
parent: DirectoryReceipt;
|
|
20
|
-
}>;
|
|
17
|
+
export type FileLockSyncRootDirectoryReceipt = FileLockSyncRootFileReceipt;
|
|
21
18
|
export type FileLockSyncRootDiskSnapshot = {
|
|
22
19
|
ownershipToken?: never;
|
|
23
20
|
payload: unknown;
|
|
24
21
|
raw: string;
|
|
25
|
-
stat:
|
|
22
|
+
stat: BigIntStats;
|
|
26
23
|
};
|
|
27
24
|
export type FileLockSyncRootSnapshot = Readonly<{
|
|
28
25
|
receipt: FileLockSyncRootFileReceipt;
|
|
@@ -143,7 +143,7 @@ export function readFileLockSyncRootSnapshot(pathAuthority, options = {}) {
|
|
|
143
143
|
throw error;
|
|
144
144
|
}
|
|
145
145
|
assertRegularFile(after, pathAuthority.authority.hardlinks);
|
|
146
|
-
const stat = fs.fstatSync(fd);
|
|
146
|
+
const stat = fs.fstatSync(fd, { bigint: true });
|
|
147
147
|
if (expectedReceipt) {
|
|
148
148
|
assertRetainedParentCurrent(pathAuthority, parent);
|
|
149
149
|
}
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import type { FileLockSyncAcquireOptions } from "./file-lock-sync.js";
|
|
2
|
-
import type {
|
|
3
|
-
type CapturedRootSyncAcquireOptions<TPayload extends Record<string, unknown>> = Readonly<{
|
|
4
|
-
compromiseCheckIntervalMs?: number;
|
|
5
|
-
lockPath?: string;
|
|
6
|
-
onCompromised?: (info: SidecarLockCompromisedInfo) => void;
|
|
2
|
+
import type { SidecarLockRetryOptions } from "./sidecar-lock-types.js";
|
|
3
|
+
type CapturedRootSyncAcquireOptions<TPayload extends Record<string, unknown>> = Readonly<Pick<FileLockSyncAcquireOptions<TPayload>, "compromiseCheckIntervalMs" | "lockPath" | "onCompromised" | "parsePayload" | "payload" | "reentrantOwner" | "staleRecovery" | "timeoutMs"> & {
|
|
7
4
|
optionsReceiver: FileLockSyncAcquireOptions<TPayload>;
|
|
8
|
-
parsePayload?: (raw: string) => unknown;
|
|
9
|
-
payload: () => TPayload;
|
|
10
|
-
reentrantOwner?: string;
|
|
11
5
|
retry: Readonly<SidecarLockRetryOptions>;
|
|
12
6
|
shouldReclaim?: FileLockSyncAcquireOptions<TPayload>["shouldReclaim"];
|
|
13
7
|
shouldRemoveStaleLock?: FileLockSyncAcquireOptions<TPayload>["shouldRemoveStaleLock"];
|
|
14
8
|
staleMs: number;
|
|
15
|
-
staleRecovery?: SidecarLockStaleRecovery;
|
|
16
|
-
timeoutMs?: number;
|
|
17
9
|
}>;
|
|
18
10
|
export declare function captureRootSyncAcquireOptions<TPayload extends Record<string, unknown>>(options: FileLockSyncAcquireOptions<TPayload>): CapturedRootSyncAcquireOptions<TPayload>;
|
|
19
11
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DenyMutationPolicy } from "./deny-mutations.js";
|
|
1
2
|
import { type RootContext } from "./root-context.js";
|
|
2
3
|
import type { Root } from "./root-impl.js";
|
|
3
4
|
import type { RootDefaults } from "./root-options.js";
|
|
@@ -7,10 +8,7 @@ export type FileLockSyncRootAuthority = Readonly<{
|
|
|
7
8
|
adapter: object;
|
|
8
9
|
context: RootContext;
|
|
9
10
|
assertBeforeMutation?: () => void;
|
|
10
|
-
denyMutations?: Readonly<
|
|
11
|
-
paths?: readonly string[];
|
|
12
|
-
prefixes?: readonly string[];
|
|
13
|
-
}>;
|
|
11
|
+
denyMutations?: Readonly<DenyMutationPolicy>;
|
|
14
12
|
hardlinks?: RootDefaults["hardlinks"];
|
|
15
13
|
mutationPolicy: RootPathResolutionPolicy;
|
|
16
14
|
readPolicy: RootPathResolutionPolicy;
|
|
@@ -240,7 +240,7 @@ export function acquireFileLockSync(targetPath, options) {
|
|
|
240
240
|
createdSnapshot = {
|
|
241
241
|
raw,
|
|
242
242
|
payload,
|
|
243
|
-
stat: fs.fstatSync(fd),
|
|
243
|
+
stat: fs.fstatSync(fd, { bigint: true }),
|
|
244
244
|
ownershipToken,
|
|
245
245
|
};
|
|
246
246
|
createdHeld = {
|
|
@@ -280,7 +280,7 @@ export function acquireFileLockSync(targetPath, options) {
|
|
|
280
280
|
const failed = createdSnapshot ?? { payload: null };
|
|
281
281
|
if (!failed.stat) {
|
|
282
282
|
try {
|
|
283
|
-
failed.stat = fs.fstatSync(fd);
|
|
283
|
+
failed.stat = fs.fstatSync(fd, { bigint: true });
|
|
284
284
|
}
|
|
285
285
|
catch {
|
|
286
286
|
// Missing identity leaves the sidecar in place, but must not skip close.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Readable } from "node:stream";
|
|
2
|
-
import { type SyncStoreDirectoryReceipt } from "./file-store-sync-directory.js";
|
|
2
|
+
import { ensureSyncStoreDirectory, type SyncStoreDirectoryReceipt } from "./file-store-sync-directory.js";
|
|
3
3
|
import { type Root } from "./root.js";
|
|
4
4
|
import { prepareSecretFileWrite } from "./secret-file.js";
|
|
5
5
|
export type SyncParentGuard = SyncStoreDirectoryReceipt;
|
|
@@ -23,12 +23,8 @@ export declare function ensureParentSync(params: {
|
|
|
23
23
|
filePath: string;
|
|
24
24
|
mode: number;
|
|
25
25
|
}): SyncParentGuard;
|
|
26
|
-
export declare function ensureStoreDirectorySync(params:
|
|
27
|
-
|
|
28
|
-
targetDir: string;
|
|
29
|
-
mode: number;
|
|
30
|
-
messagePrefix: "private store" | "store";
|
|
31
|
-
}): SyncParentGuard;
|
|
26
|
+
export declare function ensureStoreDirectorySync(params: Parameters<typeof ensureSyncStoreDirectory>[0]): SyncParentGuard;
|
|
27
|
+
export declare function literalStoreRootPath(relativePath: string): string;
|
|
32
28
|
export declare function assertRelativePath(relativePath: string): string;
|
|
33
29
|
export declare function resolveStorePath(rootDir: string, relativePath: string): string;
|
|
34
30
|
export declare function assertFileStoreMaxBytes(size: number, limit: number | undefined): void;
|
|
@@ -7,8 +7,7 @@ import { FsSafeError } from "./errors.js";
|
|
|
7
7
|
import { assertSyncStoreDirectoryReceipt, ensureSyncStoreDirectory, } from "./file-store-sync-directory.js";
|
|
8
8
|
import { isPathInside, splitSafeRelativePath } from "./path.js";
|
|
9
9
|
import { resolveOpenedFileRealPathForHandle, root } from "./root.js";
|
|
10
|
-
import {
|
|
11
|
-
import { RootHandle } from "./root-impl.js";
|
|
10
|
+
import { rootFromDirectoryGuard } from "./root-impl.js";
|
|
12
11
|
import { prepareSecretFileWrite } from "./secret-file.js";
|
|
13
12
|
import { resolveSecureTempRoot } from "./secure-temp-dir.js";
|
|
14
13
|
import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
|
|
@@ -16,7 +15,7 @@ import { readRegularFile } from "./regular-file.js";
|
|
|
16
15
|
import { errorCauseOptions } from "./root-errors.js";
|
|
17
16
|
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
18
17
|
export async function ensureParentInRoot(scopedRoot, relativePath, mode) {
|
|
19
|
-
const parent = path.posix.dirname(relativePath);
|
|
18
|
+
const parent = literalStoreRootPath(path.posix.dirname(relativePath));
|
|
20
19
|
if (parent === ".") {
|
|
21
20
|
return;
|
|
22
21
|
}
|
|
@@ -32,13 +31,7 @@ export async function openWritableStoreRoot(params) {
|
|
|
32
31
|
export async function openPrivateStoreLockRoot(params) {
|
|
33
32
|
const { parentGuard } = await prepareSecretFileWrite(params);
|
|
34
33
|
// Bind to the admitted parent, never resolve a replacement into a fresh capability.
|
|
35
|
-
return
|
|
36
|
-
rootDir: parentGuard.dir,
|
|
37
|
-
rootGuard: { dir: parentGuard.realPath, realPath: parentGuard.realPath, stat: parentGuard.stat },
|
|
38
|
-
rootReal: parentGuard.realPath,
|
|
39
|
-
rootWithSep: ensureTrailingSep(parentGuard.realPath),
|
|
40
|
-
rootIdentity: { dev: parentGuard.stat.dev, ino: parentGuard.stat.ino },
|
|
41
|
-
}, { hardlinks: "reject" });
|
|
34
|
+
return rootFromDirectoryGuard(parentGuard, { hardlinks: "reject" });
|
|
42
35
|
}
|
|
43
36
|
async function chmodDirectoryInRootBestEffort(scopedRoot, relativePath, mode) {
|
|
44
37
|
const dirPath = await scopedRoot.resolve(relativePath);
|
|
@@ -120,6 +113,10 @@ export function ensureStoreDirectorySync(params) {
|
|
|
120
113
|
assertSyncStoreDirectoryReceipt(guard);
|
|
121
114
|
return guard;
|
|
122
115
|
}
|
|
116
|
+
// Store keys and directory-entry names are literal, unlike Root's home syntax.
|
|
117
|
+
export function literalStoreRootPath(relativePath) {
|
|
118
|
+
return relativePath === "~" || relativePath.startsWith("~/") ? `./${relativePath}` : relativePath;
|
|
119
|
+
}
|
|
123
120
|
export function assertRelativePath(relativePath) {
|
|
124
121
|
const raw = relativePath.trim();
|
|
125
122
|
if (!raw || raw !== relativePath) {
|
|
@@ -2,6 +2,7 @@ import fsSync, {} from "node:fs";
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
|
+
import { literalStoreRootPath } from "./file-store-boundary.js";
|
|
5
6
|
import { isPathInside } from "./path.js";
|
|
6
7
|
import { realpathSync } from "./realpath.js";
|
|
7
8
|
import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
|
|
@@ -22,10 +23,10 @@ export async function pruneExpiredStoreEntries(params) {
|
|
|
22
23
|
const rootGuard = {
|
|
23
24
|
dir: rootReal,
|
|
24
25
|
realPath: rootReal,
|
|
25
|
-
stat: fsSync.lstatSync(rootReal),
|
|
26
|
+
stat: fsSync.lstatSync(rootReal, { bigint: true }),
|
|
26
27
|
};
|
|
27
28
|
async function assertRootGuard() {
|
|
28
|
-
const stat = fsSync.lstatSync(rootGuard.dir);
|
|
29
|
+
const stat = fsSync.lstatSync(rootGuard.dir, { bigint: true });
|
|
29
30
|
if (stat.isSymbolicLink() ||
|
|
30
31
|
!stat.isDirectory() ||
|
|
31
32
|
stat.dev !== rootGuard.stat.dev ||
|
|
@@ -35,7 +36,7 @@ export async function pruneExpiredStoreEntries(params) {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
async function readStableDirectory(dir) {
|
|
38
|
-
const before = observeOrNull(() => fsSync.lstatSync(dir));
|
|
39
|
+
const before = observeOrNull(() => fsSync.lstatSync(dir, { bigint: true }));
|
|
39
40
|
if (!before || before.isSymbolicLink() || !before.isDirectory()) {
|
|
40
41
|
return null;
|
|
41
42
|
}
|
|
@@ -47,7 +48,7 @@ export async function pruneExpiredStoreEntries(params) {
|
|
|
47
48
|
if (!entries) {
|
|
48
49
|
return null;
|
|
49
50
|
}
|
|
50
|
-
const after = observeOrNull(() => fsSync.lstatSync(dir));
|
|
51
|
+
const after = observeOrNull(() => fsSync.lstatSync(dir, { bigint: true }));
|
|
51
52
|
if (!after || before.dev !== after.dev || before.ino !== after.ino) {
|
|
52
53
|
return null;
|
|
53
54
|
}
|
|
@@ -74,13 +75,13 @@ export async function pruneExpiredStoreEntries(params) {
|
|
|
74
75
|
await assertRootGuard();
|
|
75
76
|
// Keep empty-dir pruning on the same root-bounded remove path as files;
|
|
76
77
|
// the Root fallback handles empty directories without recursive delete.
|
|
77
|
-
await scopedRoot.remove(relativePath, REMOVE_EMPTY_DIRECTORY_OPTIONS).catch(() => undefined);
|
|
78
|
+
await scopedRoot.remove(literalStoreRootPath(relativePath), REMOVE_EMPTY_DIRECTORY_OPTIONS).catch(() => undefined);
|
|
78
79
|
}
|
|
79
80
|
continue;
|
|
80
81
|
}
|
|
81
82
|
if (stat.isFile() && now - stat.mtimeMs > params.options.ttlMs) {
|
|
82
83
|
await assertRootGuard();
|
|
83
|
-
await scopedRoot.remove(relativePath, {
|
|
84
|
+
await scopedRoot.remove(literalStoreRootPath(relativePath), {
|
|
84
85
|
assertBeforeMutation: () => {
|
|
85
86
|
// Removal preparation can outlive the expiry observation above.
|
|
86
87
|
const current = fsSync.lstatSync(fullPath);
|
|
@@ -12,14 +12,11 @@ export type FileStoreOptions = {
|
|
|
12
12
|
mode?: number;
|
|
13
13
|
maxBytes?: number;
|
|
14
14
|
};
|
|
15
|
-
export type FileStoreWriteOptions = {
|
|
15
|
+
export type FileStoreWriteOptions = Partial<Pick<FileStoreOptions, "dirMode" | "mode" | "maxBytes"> & {
|
|
16
16
|
/** Override store durability; defaults to the store option, then true. */
|
|
17
|
-
durable
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
maxBytes?: number;
|
|
21
|
-
tempPrefix?: string;
|
|
22
|
-
};
|
|
17
|
+
durable: boolean;
|
|
18
|
+
tempPrefix: string;
|
|
19
|
+
}>;
|
|
23
20
|
export type FileStoreReadOptions = RootReadOptions & {
|
|
24
21
|
encoding?: BufferEncoding;
|
|
25
22
|
};
|
|
@@ -3,7 +3,7 @@ import { normalizeMaxBytes } from "./byte-budget.js";
|
|
|
3
3
|
import { readFileDescriptorBoundedSync } from "./bounded-read.js";
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
5
|
import { pruneExpiredStoreEntries } from "./file-store-prune.js";
|
|
6
|
-
import { assertFileStoreMaxBytes, assertRelativePath, ensureParentInRoot, openPrivateStoreLockRoot, openWritableStoreRoot, readFileStoreCopySource, resolveStorePath, writeStreamToTempSource, } from "./file-store-boundary.js";
|
|
6
|
+
import { assertFileStoreMaxBytes, assertRelativePath, ensureParentInRoot, literalStoreRootPath, openPrivateStoreLockRoot, openWritableStoreRoot, readFileStoreCopySource, resolveStorePath, writeStreamToTempSource, } from "./file-store-boundary.js";
|
|
7
7
|
import { writeFileSyncAtomic } from "./file-store-sync-write.js";
|
|
8
8
|
import { createJsonStore } from "./json-document-store.js";
|
|
9
9
|
import { stringifyJsonDocument } from "./json-stringify.js";
|
|
@@ -61,7 +61,7 @@ function handleSyncStoreReadOpenFailure(opened) {
|
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
async function copyIntoRoot(params) {
|
|
64
|
-
const relativePath =
|
|
64
|
+
const relativePath = params.relativePath;
|
|
65
65
|
const destination = resolveStorePath(params.rootDir, relativePath);
|
|
66
66
|
assertNoWindowsPathAlias(params.sourcePath, "filesystem", "source path uses a Windows filesystem namespace alias");
|
|
67
67
|
const sourceStat = syncFs.lstatSync(params.sourcePath);
|
|
@@ -75,7 +75,7 @@ async function copyIntoRoot(params) {
|
|
|
75
75
|
maxBytes: params.maxBytes,
|
|
76
76
|
});
|
|
77
77
|
await ensureParentInRoot(scopedRoot, relativePath, params.dirMode);
|
|
78
|
-
await scopedRoot.copyIn(relativePath, params.sourcePath, {
|
|
78
|
+
await scopedRoot.copyIn(literalStoreRootPath(relativePath), params.sourcePath, {
|
|
79
79
|
durable: params.durable,
|
|
80
80
|
maxBytes: params.maxBytes,
|
|
81
81
|
mkdir: false,
|
|
@@ -97,8 +97,7 @@ export function fileStore(options) {
|
|
|
97
97
|
return await root(rootDir, { hardlinks: "reject", maxBytes });
|
|
98
98
|
}
|
|
99
99
|
async function write(relativePath, data, writeOptions) {
|
|
100
|
-
const
|
|
101
|
-
const destination = resolveStorePath(rootDir, safeRelativePath);
|
|
100
|
+
const destination = resolveStorePath(rootDir, relativePath);
|
|
102
101
|
const content = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
103
102
|
const writeMaxBytes = normalizeMaxBytes(writeOptions?.maxBytes, { defaultValue: maxBytes });
|
|
104
103
|
assertFileStoreMaxBytes(content.byteLength, writeMaxBytes);
|
|
@@ -121,8 +120,8 @@ export function fileStore(options) {
|
|
|
121
120
|
dirMode: writeDirMode,
|
|
122
121
|
maxBytes: writeMaxBytes,
|
|
123
122
|
});
|
|
124
|
-
await ensureParentInRoot(scopedRoot,
|
|
125
|
-
await scopedRoot.write(
|
|
123
|
+
await ensureParentInRoot(scopedRoot, relativePath, writeDirMode);
|
|
124
|
+
await scopedRoot.write(literalStoreRootPath(relativePath), content, {
|
|
126
125
|
mkdir: false,
|
|
127
126
|
mode: writeMode,
|
|
128
127
|
durable: writeDurable,
|
|
@@ -135,8 +134,7 @@ export function fileStore(options) {
|
|
|
135
134
|
root: openRoot,
|
|
136
135
|
write,
|
|
137
136
|
writeStream: async (relativePath, stream, writeOptions) => {
|
|
138
|
-
const
|
|
139
|
-
const destination = resolveStorePath(rootDir, safeRelativePath);
|
|
137
|
+
const destination = resolveStorePath(rootDir, relativePath);
|
|
140
138
|
const configuredLimit = normalizeMaxBytes(writeOptions?.maxBytes, { defaultValue: maxBytes });
|
|
141
139
|
const limit = configuredLimit ?? (privateMode ? DEFAULT_ROOT_MAX_BYTES : undefined);
|
|
142
140
|
if (privateMode) {
|
|
@@ -172,7 +170,7 @@ export function fileStore(options) {
|
|
|
172
170
|
try {
|
|
173
171
|
await copyIntoRoot({
|
|
174
172
|
rootDir,
|
|
175
|
-
relativePath
|
|
173
|
+
relativePath,
|
|
176
174
|
sourcePath: staged.path,
|
|
177
175
|
durable: writeDurable,
|
|
178
176
|
maxBytes: limit,
|
|
@@ -214,17 +212,17 @@ export function fileStore(options) {
|
|
|
214
212
|
tempPrefix: writeOptions?.tempPrefix,
|
|
215
213
|
});
|
|
216
214
|
},
|
|
217
|
-
open: async (relativePath, readOptions) => await (await openRoot()).open(assertRelativePath(relativePath), readOptions),
|
|
218
|
-
read: async (relativePath, readOptions) => await (await openRoot()).read(assertRelativePath(relativePath), readOptions),
|
|
219
|
-
readBytes: async (relativePath, readOptions) => await (await openRoot()).readBytes(assertRelativePath(relativePath), readOptions),
|
|
215
|
+
open: async (relativePath, readOptions) => await (await openRoot()).open(literalStoreRootPath(assertRelativePath(relativePath)), readOptions),
|
|
216
|
+
read: async (relativePath, readOptions) => await (await openRoot()).read(literalStoreRootPath(assertRelativePath(relativePath)), readOptions),
|
|
217
|
+
readBytes: async (relativePath, readOptions) => await (await openRoot()).readBytes(literalStoreRootPath(assertRelativePath(relativePath)), readOptions),
|
|
220
218
|
readText: async (relativePath, readOptions) => {
|
|
221
219
|
const { encoding = "utf8", ...options } = readOptions ?? {};
|
|
222
|
-
return (await (await openRoot()).read(assertRelativePath(relativePath), options)).buffer
|
|
220
|
+
return (await (await openRoot()).read(literalStoreRootPath(assertRelativePath(relativePath)), options)).buffer
|
|
223
221
|
.toString(encoding);
|
|
224
222
|
},
|
|
225
223
|
readTextIfExists: async (relativePath, readOptions) => {
|
|
226
224
|
try {
|
|
227
|
-
return await (await openRoot()).readText(assertRelativePath(relativePath), readOptions);
|
|
225
|
+
return await (await openRoot()).readText(literalStoreRootPath(assertRelativePath(relativePath)), readOptions);
|
|
228
226
|
}
|
|
229
227
|
catch (error) {
|
|
230
228
|
if (isNotFound(error)) {
|
|
@@ -235,12 +233,12 @@ export function fileStore(options) {
|
|
|
235
233
|
},
|
|
236
234
|
readJson: async (relativePath, readOptions) => {
|
|
237
235
|
const { encoding = "utf8", ...options } = readOptions ?? {};
|
|
238
|
-
return JSON.parse((await (await openRoot()).read(assertRelativePath(relativePath), options)).buffer
|
|
236
|
+
return JSON.parse((await (await openRoot()).read(literalStoreRootPath(assertRelativePath(relativePath)), options)).buffer
|
|
239
237
|
.toString(encoding));
|
|
240
238
|
},
|
|
241
239
|
readJsonIfExists: async (relativePath, readOptions) => {
|
|
242
240
|
try {
|
|
243
|
-
return await (await openRoot()).readJson(assertRelativePath(relativePath), readOptions);
|
|
241
|
+
return await (await openRoot()).readJson(literalStoreRootPath(assertRelativePath(relativePath)), readOptions);
|
|
244
242
|
}
|
|
245
243
|
catch (error) {
|
|
246
244
|
if (isNotFound(error)) {
|
|
@@ -250,9 +248,9 @@ export function fileStore(options) {
|
|
|
250
248
|
}
|
|
251
249
|
},
|
|
252
250
|
remove: async (relativePath) => {
|
|
253
|
-
await (await openRoot()).remove(assertRelativePath(relativePath));
|
|
251
|
+
await (await openRoot()).remove(literalStoreRootPath(assertRelativePath(relativePath)));
|
|
254
252
|
},
|
|
255
|
-
exists: async (relativePath) => await (await openRoot()).exists(assertRelativePath(relativePath)),
|
|
253
|
+
exists: async (relativePath) => await (await openRoot()).exists(literalStoreRootPath(assertRelativePath(relativePath))),
|
|
256
254
|
writeText: async (relativePath, data, writeOptions) => await write(relativePath, data, writeOptions),
|
|
257
255
|
writeJson: async (relativePath, data, writeOptions) => {
|
|
258
256
|
const trailingNewline = writeOptions?.trailingNewline;
|
|
@@ -269,7 +267,7 @@ export function fileStore(options) {
|
|
|
269
267
|
} : {}),
|
|
270
268
|
readIfExists: async () => {
|
|
271
269
|
try {
|
|
272
|
-
return await (await openRoot()).readJson(
|
|
270
|
+
return await (await openRoot()).readJson(literalStoreRootPath(relativePath));
|
|
273
271
|
}
|
|
274
272
|
catch (error) {
|
|
275
273
|
if (isNotFound(error)) {
|
|
@@ -278,7 +276,7 @@ export function fileStore(options) {
|
|
|
278
276
|
throw error;
|
|
279
277
|
}
|
|
280
278
|
},
|
|
281
|
-
readRequired: async () => await (await openRoot()).readJson(
|
|
279
|
+
readRequired: async () => await (await openRoot()).readJson(literalStoreRootPath(relativePath)),
|
|
282
280
|
write: async (value, options) => {
|
|
283
281
|
const json = stringifyJsonDocument(value, null, 2);
|
|
284
282
|
await write(relativePath, options?.trailingNewline === false ? json : `${json}\n`, { durable: options?.durable });
|
|
@@ -36,15 +36,6 @@ export const GUEST_FILESYSTEM_RENAME_NO_REPLACE_PYTHON = [
|
|
|
36
36
|
" is_linux = sys.platform.startswith('linux')",
|
|
37
37
|
" if is_linux:",
|
|
38
38
|
" rename_fn = getattr(libc, 'renameat2', None)",
|
|
39
|
-
" if rename_fn is None:",
|
|
40
|
-
" os.link(",
|
|
41
|
-
" src_basename,",
|
|
42
|
-
" dst_basename,",
|
|
43
|
-
" src_dir_fd=src_parent_fd,",
|
|
44
|
-
" dst_dir_fd=dst_parent_fd,",
|
|
45
|
-
" follow_symlinks=False,",
|
|
46
|
-
" )",
|
|
47
|
-
" return",
|
|
48
39
|
" flags = 1 # RENAME_NOREPLACE",
|
|
49
40
|
" elif sys.platform == 'darwin':",
|
|
50
41
|
" rename_fn = getattr(libc, 'renameatx_np', None)",
|
|
@@ -52,32 +43,33 @@ export const GUEST_FILESYSTEM_RENAME_NO_REPLACE_PYTHON = [
|
|
|
52
43
|
" else:",
|
|
53
44
|
" rename_fn = None",
|
|
54
45
|
" flags = 0",
|
|
55
|
-
" if rename_fn is None:",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
46
|
+
" if rename_fn is not None:",
|
|
47
|
+
" rename_fn.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_uint]",
|
|
48
|
+
" rename_fn.restype = ctypes.c_int",
|
|
49
|
+
" result = rename_fn(",
|
|
50
|
+
" src_parent_fd,",
|
|
51
|
+
" os.fsencode(src_basename),",
|
|
52
|
+
" dst_parent_fd,",
|
|
53
|
+
" os.fsencode(dst_basename),",
|
|
54
|
+
" flags,",
|
|
55
|
+
" )",
|
|
56
|
+
" if result == 0:",
|
|
57
|
+
" return",
|
|
67
58
|
" error_code = ctypes.get_errno()",
|
|
68
59
|
" unsupported_codes = {errno.ENOSYS, errno.EINVAL, errno.ENOTSUP}",
|
|
69
60
|
" if hasattr(errno, 'EOPNOTSUPP'):",
|
|
70
61
|
" unsupported_codes.add(errno.EOPNOTSUPP)",
|
|
71
|
-
" if is_linux
|
|
72
|
-
" os.
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
62
|
+
" if not is_linux or error_code not in unsupported_codes:",
|
|
63
|
+
" raise OSError(error_code, os.strerror(error_code), dst_basename)",
|
|
64
|
+
" elif not is_linux:",
|
|
65
|
+
" raise OSError(errno.ENOSYS, 'atomic no-replace rename is unavailable')",
|
|
66
|
+
" os.link(",
|
|
67
|
+
" src_basename,",
|
|
68
|
+
" dst_basename,",
|
|
69
|
+
" src_dir_fd=src_parent_fd,",
|
|
70
|
+
" dst_dir_fd=dst_parent_fd,",
|
|
71
|
+
" follow_symlinks=False,",
|
|
72
|
+
" )",
|
|
81
73
|
].join("\n");
|
|
82
74
|
export const GUEST_FILESYSTEM_CREATE_EXCLUSIVE_PYTHON = [
|
|
83
75
|
"def create_exclusive(parent_fd, basename, stdin_buffer):",
|