akanjs 3.0.2 → 3.1.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/base/baseEnv.ts +0 -4
- package/base/primitiveRegistry.ts +2 -2
- package/client/cookie.ts +5 -1
- package/client/csrLocation.ts +122 -0
- package/client/csrTypes.ts +32 -4
- package/client/device.ts +2 -1
- package/client/frameConfig.ts +78 -7
- package/client/index.ts +3 -0
- package/client/makePageProto.tsx +3 -2
- package/client/native/external-view.ts +1 -0
- package/client/route/RootLayoutDefinition.ts +7 -1
- package/client/route/RouteHead.ts +108 -0
- package/client/route/index.ts +1 -0
- package/client/router.ts +36 -23
- package/client/rscNavigation.ts +8 -2
- package/client/viewportMeta.ts +60 -0
- package/client/webManifest.ts +18 -0
- package/common/Logger.ts +7 -2
- package/common/PipelineNames.ts +31 -0
- package/common/PipelinePattern.ts +70 -0
- package/common/PipelinePlanSchema.ts +490 -0
- package/common/backoff.ts +14 -0
- package/common/index.ts +39 -0
- package/common/pipelinePlan.ts +259 -0
- package/common/routeConvention.ts +1 -0
- package/common/types.ts +17 -0
- package/constant/constantRegistry.ts +26 -6
- package/dictionary/base.dictionary.ts +8 -0
- package/dictionary/trans.ts +9 -1
- package/document/into.ts +5 -0
- package/fetch/client/fetchClient.ts +135 -31
- package/fetch/client/httpClient.ts +45 -0
- package/fetch/client/wsClient.ts +125 -16
- package/fetch/fetchType/buildFetch.type.ts +1 -0
- package/index.ts +243 -10
- package/package.json +1 -5
- package/server/akanApp.ts +5 -2
- package/server/akanServer.ts +44 -8
- package/server/artifact/builderRpc.ts +8 -3
- package/server/artifact/ipcTypes.ts +5 -2
- package/server/di/diLifecycle.ts +39 -3
- package/server/di/utils.ts +28 -1
- package/server/ed25519Key.ts +48 -0
- package/server/index.ts +1 -0
- package/server/machine/index.ts +2 -0
- package/server/machine/machineAccount.ts +27 -0
- package/server/machine/machineToken.ts +151 -0
- package/server/mcp/McpApps.ts +256 -0
- package/server/mcp/McpDispatcher.ts +31 -7
- package/server/mcp/McpRouter.ts +209 -46
- package/server/ops/opsToken.ts +3 -10
- package/server/resolver/database.resolver.ts +3 -0
- package/server/resolver/signal.resolver.ts +40 -3
- package/server/routeElementComposer.tsx +78 -2
- package/server/routeState.ts +6 -0
- package/server/routeTreeBuilder.ts +26 -9
- package/server/routing/apiRouter.ts +6 -3
- package/server/routing/roomReplay.ts +88 -0
- package/server/rscClient.tsx +53 -8
- package/server/rscWorker.tsx +141 -27
- package/server/rscWorkerHost.ts +18 -5
- package/server/sitemap.ts +14 -0
- package/server/ssrFromRscRenderer.tsx +12 -6
- package/server/ssrTypes.ts +3 -1
- package/server/systemPageDocument.tsx +38 -30
- package/server/types.tsx +2 -0
- package/server/webRouter.ts +74 -5
- package/service/injectInfo.ts +9 -1
- package/service/ipcTypes.ts +2 -1
- package/service/predefinedAdaptor/database.adaptor.ts +1 -146
- package/service/predefinedAdaptor/queue.adaptor.ts +44 -6
- package/service/predefinedAdaptor/queueBackoff.ts +12 -0
- package/service/predefinedAdaptor/solidQueue.adaptor.ts +17 -13
- package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +44 -2
- package/service/predefinedAdaptor/sql/dialect/postgres.ts +3 -0
- package/service/predefinedAdaptor/sql/dialect/sqlite.ts +5 -2
- package/service/predefinedAdaptor/sql/search/fts5.ts +1 -1
- package/service/predefinedAdaptor/sql/types.ts +8 -6
- package/service/predefinedAdaptor/sql/values.ts +0 -23
- package/service/serve.ts +5 -1
- package/signal/agent.signal.ts +1 -1
- package/signal/base.signal.ts +2 -2
- package/signal/endpointIdempotency.ts +53 -0
- package/signal/internalArg.ts +14 -0
- package/signal/mcp/McpDocument.ts +38 -1
- package/signal/mcp/mcpProtocol.ts +18 -0
- package/signal/signalContext.ts +58 -30
- package/signal/signalRegistry.ts +14 -4
- package/signal/types.ts +18 -3
- package/store/agent/StoreSurfaceSource.ts +1 -1
- package/store/agentic/StToolBuilder.ts +3 -0
- package/test/conformance.ts +9 -33
- package/types/base/baseEnv.d.ts +0 -4
- package/types/base/primitiveRegistry.d.ts +1 -1
- package/types/client/csrLocation.d.ts +32 -0
- package/types/client/csrTypes.d.ts +40 -4
- package/types/client/frameConfig.d.ts +14 -2
- package/types/client/index.d.ts +3 -0
- package/types/client/native/external-view.d.ts +1 -0
- package/types/client/route/RootLayoutDefinition.d.ts +2 -1
- package/types/client/route/RouteHead.d.ts +13 -0
- package/types/client/route/index.d.ts +1 -0
- package/types/client/router.d.ts +6 -0
- package/types/client/rscNavigation.d.ts +4 -0
- package/types/client/viewportMeta.d.ts +18 -0
- package/types/client/webManifest.d.ts +4 -0
- package/types/common/PipelineNames.d.ts +6 -0
- package/types/common/PipelinePattern.d.ts +14 -0
- package/types/common/PipelinePlanSchema.d.ts +9 -0
- package/types/common/backoff.d.ts +10 -0
- package/types/common/index.d.ts +5 -0
- package/types/common/pipelinePlan.d.ts +224 -0
- package/types/common/types.d.ts +16 -0
- package/types/constant/constantRegistry.d.ts +5 -2
- package/types/dictionary/base.dictionary.d.ts +1 -1
- package/types/dictionary/dictionary.d.ts +8 -8
- package/types/document/into.d.ts +9 -0
- package/types/fetch/client/fetchClient.d.ts +31 -4
- package/types/fetch/client/httpClient.d.ts +8 -0
- package/types/fetch/client/wsClient.d.ts +26 -2
- package/types/fetch/fetchType/buildFetch.type.d.ts +1 -0
- package/types/index.d.ts +230 -9
- package/types/server/akanServer.d.ts +16 -1
- package/types/server/artifact/builderRpc.d.ts +7 -2
- package/types/server/artifact/ipcTypes.d.ts +5 -1
- package/types/server/di/utils.d.ts +1 -0
- package/types/server/ed25519Key.d.ts +13 -0
- package/types/server/index.d.ts +1 -0
- package/types/server/machine/index.d.ts +2 -0
- package/types/server/machine/machineAccount.d.ts +5 -0
- package/types/server/machine/machineToken.d.ts +29 -0
- package/types/server/machine.d.ts +1 -0
- package/types/server/mcp/McpApps.d.ts +50 -0
- package/types/server/mcp/McpDispatcher.d.ts +4 -1
- package/types/server/mcp/McpRouter.d.ts +4 -0
- package/types/server/resolver/signal.resolver.d.ts +2 -1
- package/types/server/routeElementComposer.d.ts +24 -4
- package/types/server/routeState.d.ts +4 -1
- package/types/server/routing/roomReplay.d.ts +24 -0
- package/types/server/rscWorkerHost.d.ts +5 -2
- package/types/server/sitemap.d.ts +2 -0
- package/types/server/ssrFromRscRenderer.d.ts +3 -3
- package/types/server/ssrTypes.d.ts +4 -1
- package/types/server/systemPageDocument.d.ts +2 -0
- package/types/server/types.d.ts +4 -1
- package/types/server/webRouter.d.ts +3 -1
- package/types/service/ipcTypes.d.ts +2 -0
- package/types/service/predefinedAdaptor/database.adaptor.d.ts +1 -24
- package/types/service/predefinedAdaptor/queue.adaptor.d.ts +10 -3
- package/types/service/predefinedAdaptor/queueBackoff.d.ts +4 -0
- package/types/service/predefinedAdaptor/solidQueue.adaptor.d.ts +3 -3
- package/types/service/predefinedAdaptor/sql/SqlDocumentStore.d.ts +6 -1
- package/types/service/predefinedAdaptor/sql/dialect/postgres.d.ts +1 -0
- package/types/service/predefinedAdaptor/sql/dialect/sqlite.d.ts +1 -0
- package/types/service/predefinedAdaptor/sql/search/fts5.d.ts +1 -1
- package/types/service/predefinedAdaptor/sql/types.d.ts +9 -5
- package/types/service/predefinedAdaptor/sql/values.d.ts +0 -3
- package/types/service/serve.d.ts +3 -0
- package/types/signal/endpointIdempotency.d.ts +7 -0
- package/types/signal/internalArg.d.ts +10 -0
- package/types/signal/mcp/McpDocument.d.ts +8 -0
- package/types/signal/mcp/mcpProtocol.d.ts +17 -0
- package/types/signal/signalContext.d.ts +5 -3
- package/types/signal/signalRegistry.d.ts +4 -4
- package/types/signal/types.d.ts +21 -1
- package/types/store/agentic/StToolBuilder.d.ts +2 -0
- package/types/test/conformance.d.ts +7 -10
- package/types/ui/Agent/Chat.d.ts +5 -1
- package/types/ui/Agent/EmbedApproval.d.ts +1 -0
- package/types/ui/Agent/index.d.ts +3 -0
- package/types/ui/Agent/useKeyboardFrame.d.ts +2 -0
- package/types/ui/Agent/useScreenActions.d.ts +18 -0
- package/types/ui/BottomSheet.d.ts +1 -0
- package/types/ui/Constant/Doc.d.ts +11 -17
- package/types/ui/Constant/index.d.ts +7 -2
- package/types/ui/Constant/schemaDoc.d.ts +11 -0
- package/types/ui/Dialog/Modal.d.ts +6 -1
- package/types/ui/Dialog/index.d.ts +1 -1
- package/types/ui/Dialog/modalSurface.d.ts +12 -0
- package/types/ui/Layout/BottomTab.d.ts +11 -2
- package/types/ui/Layout/FrameSlotFallback.d.ts +9 -0
- package/types/ui/Layout/Navbar.d.ts +4 -1
- package/types/ui/Layout/TopInset.d.ts +1 -1
- package/types/ui/Layout/index.d.ts +3 -3
- package/types/ui/Link/Action.d.ts +5 -1
- package/types/ui/Link/Anchor.d.ts +5 -3
- package/types/ui/Link/activePath.d.ts +13 -0
- package/types/ui/Link/index.d.ts +1 -1
- package/types/ui/Modal.d.ts +6 -1
- package/types/ui/Model/EditModal.d.ts +6 -1
- package/types/ui/Model/New.d.ts +6 -1
- package/types/ui/Model/ViewEditModal.d.ts +6 -1
- package/types/ui/Model/ViewModal.d.ts +6 -1
- package/types/ui/Model/newFormOrigin.d.ts +7 -0
- package/types/ui/Portal.d.ts +3 -1
- package/types/ui/Reference/origin.d.ts +12 -0
- package/types/ui/Signal/Doc.d.ts +23 -18
- package/types/ui/Signal/Listener.d.ts +2 -6
- package/types/ui/Signal/Object.d.ts +6 -10
- package/types/ui/Signal/Response.d.ts +3 -6
- package/types/ui/Signal/RestApi.d.ts +11 -15
- package/types/ui/Signal/WebSocket.d.ts +11 -21
- package/types/ui/Signal/endpointEntries.d.ts +8 -0
- package/types/ui/Signal/index.d.ts +35 -12
- package/types/ui/Signal/signalText.d.ts +178 -0
- package/types/ui/System/CSR.d.ts +2 -2
- package/types/ui/System/Client.d.ts +4 -3
- package/types/ui/System/Common.d.ts +27 -6
- package/types/ui/System/SSR.d.ts +6 -6
- package/types/ui/Tooltip.d.ts +4 -2
- package/types/ui/index.d.ts +2 -1
- package/types/ui/overlayLayer.d.ts +6 -0
- package/types/ui/overlayPosition.d.ts +17 -0
- package/types/vendor/@akanjs/native/packages/cli/src/api.d.ts +14 -3
- package/types/vendor/@akanjs/native/packages/cli/src/commands/update.d.ts +1 -1
- package/types/vendor/@akanjs/native/packages/cli/src/config.d.ts +30 -5
- package/types/vendor/@akanjs/native/packages/cli/src/lib/compat.d.ts +8 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.d.ts +5 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/distribution.d.ts +22 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/project.d.ts +4 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/publish.d.ts +16 -10
- package/types/vendor/@akanjs/native/packages/cli/src/lib/updates.d.ts +51 -7
- package/types/vendor/@akanjs/native/packages/cli/src/lib/vectors.d.ts +1 -1
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.d.ts +7 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows.d.ts +5 -0
- package/types/vendor/@akanjs/native/packages/core/src/kernel.d.ts +36 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/server.d.ts +11 -0
- package/types/vendor/@akanjs/native/plugins/external-view/src/desktop.d.ts +17 -0
- package/types/vendor/@akanjs/native/plugins/external-view/src/index.d.ts +132 -0
- package/types/vendor/@akanjs/native/plugins/external-view/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/updates/src/index.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/window/src/desktop.d.ts +4 -1
- package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +49 -0
- package/types/vendor/use-agentic/types.d.ts +2 -0
- package/types/webkit/CsrStack.d.ts +1 -1
- package/types/webkit/McpAppAgent.d.ts +14 -0
- package/types/webkit/McpAppApprovals.d.ts +8 -0
- package/types/webkit/McpAppBridge.d.ts +101 -0
- package/types/webkit/McpAppView.d.ts +21 -0
- package/types/webkit/index.d.ts +1 -0
- package/types/webkit/useLocation.d.ts +1 -1
- package/types/webkit/useVisualViewportFrame.d.ts +13 -0
- package/ui/Agent/Chat.tsx +29 -10
- package/ui/Agent/Composer.tsx +2 -1
- package/ui/Agent/EmbedApproval.tsx +17 -0
- package/ui/Agent/RichInput.tsx +1 -1
- package/ui/Agent/index.ts +2 -0
- package/ui/Agent/useKeyboardFrame.ts +10 -0
- package/ui/Agent/useScreenActions.ts +45 -0
- package/ui/BottomSheet.tsx +82 -53
- package/ui/Constant/Doc.tsx +113 -60
- package/ui/Constant/index.ts +2 -2
- package/ui/Constant/schemaDoc.ts +86 -26
- package/ui/Dialog/LegacyModal.tsx +53 -52
- package/ui/Dialog/Modal.tsx +93 -49
- package/ui/Dialog/modalSurface.ts +61 -0
- package/ui/DragAction.tsx +1 -1
- package/ui/DraggableList.tsx +1 -1
- package/ui/Dropdown.tsx +4 -6
- package/ui/KeyboardAvoiding.tsx +1 -1
- package/ui/Layout/BottomInset.tsx +20 -14
- package/ui/Layout/BottomTab.tsx +42 -16
- package/ui/Layout/FrameSlotFallback.tsx +59 -0
- package/ui/Layout/Navbar.tsx +37 -11
- package/ui/Layout/Sider.tsx +1 -1
- package/ui/Layout/TopInset.tsx +15 -14
- package/ui/Link/Action.tsx +15 -5
- package/ui/Link/Anchor.tsx +25 -13
- package/ui/Link/activePath.ts +25 -0
- package/ui/Link/index.tsx +1 -1
- package/ui/Load/Pagination.tsx +1 -1
- package/ui/Load/Units.tsx +1 -1
- package/ui/Loading/ProgressBar.tsx +1 -1
- package/ui/Modal.tsx +9 -0
- package/ui/Model/EditModal.tsx +16 -1
- package/ui/Model/New.tsx +25 -2
- package/ui/Model/NewWrapper_Client.tsx +2 -0
- package/ui/Model/ViewEditModal.tsx +9 -0
- package/ui/Model/ViewModal.tsx +16 -1
- package/ui/Model/newFormOrigin.ts +45 -0
- package/ui/Popconfirm.tsx +5 -7
- package/ui/Portal.tsx +4 -7
- package/ui/Reference/origin.ts +31 -0
- package/ui/ScreenNavigator.tsx +1 -1
- package/ui/Select.tsx +2 -7
- package/ui/Signal/Arg.tsx +2 -2
- package/ui/Signal/Doc.tsx +125 -63
- package/ui/Signal/Endpoint.tsx +11 -10
- package/ui/Signal/Listener.tsx +7 -10
- package/ui/Signal/Object.tsx +7 -14
- package/ui/Signal/Response.tsx +24 -24
- package/ui/Signal/RestApi.tsx +63 -52
- package/ui/Signal/WebSocket.tsx +65 -72
- package/ui/Signal/endpointEntries.ts +25 -0
- package/ui/Signal/index.ts +23 -6
- package/ui/Signal/signalText.ts +59 -0
- package/ui/System/CSR.tsx +34 -8
- package/ui/System/Client.tsx +36 -5
- package/ui/System/Common.tsx +76 -32
- package/ui/System/SSR.tsx +73 -31
- package/ui/Toast.tsx +1 -1
- package/ui/Tooltip.tsx +84 -30
- package/ui/index.ts +11 -1
- package/ui/overlayLayer.ts +25 -2
- package/ui/overlayPosition.ts +90 -0
- package/ui/recipe/inputRecipe.ts +8 -1
- package/ui/styles.css +152 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +22 -2
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeKernel.kt +37 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdateReports.kt +169 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdates.kt +110 -38
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeVectors.kt +20 -0
- package/vendor/@akanjs/native/native/desktop/Cargo.lock +16 -16
- package/vendor/@akanjs/native/native/desktop/src/external.rs +651 -0
- package/vendor/@akanjs/native/native/desktop/src/json.rs +23 -0
- package/vendor/@akanjs/native/native/desktop/src/lib.rs +228 -5
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeApp.swift +2 -1
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeKernel.swift +47 -1
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdateReports.swift +145 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdates.swift +112 -43
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeVectors.swift +18 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeViewController.swift +24 -2
- package/vendor/@akanjs/native/packages/cli/src/api.ts +22 -6
- package/vendor/@akanjs/native/packages/cli/src/commands/build.ts +24 -8
- package/vendor/@akanjs/native/packages/cli/src/commands/update.ts +11 -9
- package/vendor/@akanjs/native/packages/cli/src/config.ts +35 -7
- package/vendor/@akanjs/native/packages/cli/src/lib/compat.ts +2 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/configkeys.ts +6 -4
- package/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.ts +11 -1
- package/vendor/@akanjs/native/packages/cli/src/lib/distribution.ts +73 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/project.ts +15 -3
- package/vendor/@akanjs/native/packages/cli/src/lib/publish.ts +70 -23
- package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +159 -23
- package/vendor/@akanjs/native/packages/cli/src/lib/vectors.ts +2 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +9 -4
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.ts +1 -1
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop.ts +4 -2
- package/vendor/@akanjs/native/packages/cli/src/platforms/ios.ts +9 -4
- package/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.ts +25 -11
- package/vendor/@akanjs/native/packages/cli/src/platforms/windows.ts +14 -3
- package/vendor/@akanjs/native/packages/core/src/kernel.ts +49 -0
- package/vendor/@akanjs/native/packages/core/vectors/updates.json +31 -0
- package/vendor/@akanjs/native/packages/desktop/src/main.ts +3 -0
- package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +2 -0
- package/vendor/@akanjs/native/packages/desktop/src/server.ts +70 -6
- package/vendor/@akanjs/native/plugins/external-view/native-plugin.json +23 -0
- package/vendor/@akanjs/native/plugins/external-view/src/desktop.ts +321 -0
- package/vendor/@akanjs/native/plugins/external-view/src/index.ts +106 -0
- package/vendor/@akanjs/native/plugins/updates/android/UpdatesPlugin.kt +133 -41
- package/vendor/@akanjs/native/plugins/updates/ios/UpdatesPlugin.swift +101 -36
- package/vendor/@akanjs/native/plugins/updates/native-plugin.json +4 -2
- package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +15 -1
- package/vendor/@akanjs/native/plugins/updates/src/index.ts +7 -1
- package/vendor/@akanjs/native/plugins/window/native-plugin.json +4 -0
- package/vendor/@akanjs/native/plugins/window/src/desktop.ts +68 -1
- package/vendor/@akanjs/native/plugins/window/src/index.ts +47 -0
- package/vendor/use-agentic/ToolRunner.ts +8 -1
- package/vendor/use-agentic/types.ts +2 -0
- package/webkit/CsrRouteTable.ts +1 -0
- package/webkit/CsrStack.ts +9 -2
- package/webkit/McpAppAgent.ts +138 -0
- package/webkit/McpAppApprovals.ts +56 -0
- package/webkit/McpAppBridge.ts +291 -0
- package/webkit/McpAppView.ts +258 -0
- package/webkit/bootCsr.tsx +54 -5
- package/webkit/index.ts +1 -0
- package/webkit/useCsrValues.ts +16 -10
- package/webkit/useFrameRuntime.ts +10 -1
- package/webkit/useLocation.ts +4 -3
- package/webkit/useVisualViewportFrame.tsx +52 -0
- package/service/predefinedAdaptor/sql/driver/libsql.ts +0 -45
- package/types/service/predefinedAdaptor/sql/driver/libsql.d.ts +0 -20
- package/types/ui/Agent/useKeyboardInset.d.ts +0 -1
- package/types/ui/ServerPortal.d.ts +0 -15
- package/ui/Agent/useKeyboardInset.ts +0 -19
- package/ui/ServerPortal.tsx +0 -49
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
// Web bundle updates (UP-2): which bundle the shell serves, and the trial / confirm / rollback
|
|
1
|
+
// Web bundle updates (UP-2, protocol v2): which bundle the shell serves, and the trial / confirm / rollback
|
|
2
2
|
// state (the Android twin of native/ios/Sources/AkanNativeUpdates.swift, same rules and file format).
|
|
3
3
|
// @akanjs/native/plugins/updates downloads and verifies bundles and calls stage/applyPending/confirm; the
|
|
4
4
|
// activity picks the bundle at launch and rolls back a trial that never confirms.
|
|
5
5
|
//
|
|
6
|
-
// Layout: noBackupFilesDir/akan-native-updates/{state.json, bundles/<bundle>/{…, manifest.json
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
6
|
+
// Layout: noBackupFilesDir/akan-native-updates/{state.json, bundles/<bundle>/{…, manifest.signed.json}}: outside
|
|
7
|
+
// filesDir, which the filesystem plugin's `data` base exposes to the page, and out of backups (bundles download again;
|
|
8
|
+
// state.json belongs to this install). A bundle is served only while its envelope still verifies under a key of
|
|
9
|
+
// updates.publicKeys that is not revoked, and its files are all there with their sizes (checked at every launch).
|
|
10
|
+
// state.json's revokedKeys outlive reset(): a revocation is for good. Main thread only.
|
|
11
11
|
package com.akanjs.runtime
|
|
12
12
|
|
|
13
13
|
import android.content.Context
|
|
@@ -22,15 +22,18 @@ import java.security.spec.X509EncodedKeySpec
|
|
|
22
22
|
import org.json.JSONArray
|
|
23
23
|
import org.json.JSONObject
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
/** [keyId]: the key whose envelope the bundle came in. */
|
|
26
|
+
data class AkanNativeUpdateEntry(val bundle: String, val sequence: Double, val nativeApi: String, val keyId: String, val attempts: Int = 0) {
|
|
27
|
+
fun toJson(): JSONObject =
|
|
28
|
+
JSONObject().put("bundle", bundle).put("sequence", sequence).put("nativeApi", nativeApi).put("keyId", keyId).put("attempts", attempts)
|
|
27
29
|
|
|
28
30
|
companion object {
|
|
29
31
|
fun from(json: Any?): AkanNativeUpdateEntry? {
|
|
30
32
|
val o = json as? JSONObject ?: return null
|
|
31
33
|
val bundle = o.optString("bundle")
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
val keyId = o.optString("keyId")
|
|
35
|
+
if (!AkanNativeUpdates.isBundleId(bundle) || !o.has("sequence") || !o.has("nativeApi") || !AkanNativeKernel.isUpdateKeyId(keyId)) return null
|
|
36
|
+
return AkanNativeUpdateEntry(bundle, o.optDouble("sequence"), o.optString("nativeApi"), keyId, o.optInt("attempts"))
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
39
|
}
|
|
@@ -41,9 +44,10 @@ class AkanNativeUpdateState(
|
|
|
41
44
|
var trial: AkanNativeUpdateEntry? = null,
|
|
42
45
|
val failed: MutableList<String> = mutableListOf(),
|
|
43
46
|
var rolledBack: String? = null,
|
|
47
|
+
val revokedKeys: MutableList<String> = mutableListOf(),
|
|
44
48
|
) {
|
|
45
49
|
fun toJson(): JSONObject {
|
|
46
|
-
val o = JSONObject().put("failed", JSONArray(failed.takeLast(20)))
|
|
50
|
+
val o = JSONObject().put("failed", JSONArray(failed.takeLast(20))).put("revokedKeys", JSONArray(revokedKeys))
|
|
47
51
|
current?.let { o.put("current", it.toJson()) }
|
|
48
52
|
pending?.let { o.put("pending", it.toJson()) }
|
|
49
53
|
trial?.let { o.put("trial", it.toJson()) }
|
|
@@ -54,12 +58,14 @@ class AkanNativeUpdateState(
|
|
|
54
58
|
companion object {
|
|
55
59
|
fun from(o: JSONObject): AkanNativeUpdateState {
|
|
56
60
|
val failed = o.optJSONArray("failed")
|
|
61
|
+
val revoked = o.optJSONArray("revokedKeys")
|
|
57
62
|
return AkanNativeUpdateState(
|
|
58
63
|
current = AkanNativeUpdateEntry.from(o.opt("current")),
|
|
59
64
|
pending = AkanNativeUpdateEntry.from(o.opt("pending")),
|
|
60
65
|
trial = AkanNativeUpdateEntry.from(o.opt("trial")),
|
|
61
66
|
failed = MutableList(failed?.length() ?: 0) { failed!!.optString(it) }.filter(AkanNativeUpdates::isBundleId).toMutableList(),
|
|
62
67
|
rolledBack = o.optString("rolledBack").ifEmpty { null },
|
|
68
|
+
revokedKeys = MutableList(revoked?.length() ?: 0) { revoked!!.optString(it) }.filter(AkanNativeKernel::isUpdateKeyId).toMutableList(),
|
|
63
69
|
)
|
|
64
70
|
}
|
|
65
71
|
}
|
|
@@ -68,15 +74,23 @@ class AkanNativeUpdateState(
|
|
|
68
74
|
/** updates.json from the build (akan-native.config.ts `updates`), null when the app has no updates. */
|
|
69
75
|
class AkanNativeUpdateConfig(
|
|
70
76
|
val app: String,
|
|
77
|
+
val version: String,
|
|
71
78
|
val platform: String,
|
|
72
79
|
val nativeApi: String,
|
|
73
80
|
val embeddedSequence: Double,
|
|
74
81
|
val url: String,
|
|
75
|
-
|
|
82
|
+
/** updates.publicKeys in order: the order decides which key may revoke which (AkanNativeKernel.updateDecision). */
|
|
83
|
+
val keys: List<Pair<String, ByteArray>>,
|
|
76
84
|
val channel: String,
|
|
77
85
|
val readyTimeoutMs: Long,
|
|
78
86
|
val dev: Boolean,
|
|
87
|
+
/** updates.report.url: where AkanNativeUpdateReports posts what became of each release; null sends nothing. */
|
|
88
|
+
val reportUrl: String?,
|
|
79
89
|
) {
|
|
90
|
+
val ring: List<String> get() = keys.map { it.first }
|
|
91
|
+
|
|
92
|
+
fun key(keyId: String): ByteArray? = keys.firstOrNull { it.first == keyId }?.second
|
|
93
|
+
|
|
80
94
|
companion object {
|
|
81
95
|
fun load(context: Context): AkanNativeUpdateConfig? {
|
|
82
96
|
val o = try {
|
|
@@ -84,33 +98,57 @@ class AkanNativeUpdateConfig(
|
|
|
84
98
|
} catch (e: Exception) {
|
|
85
99
|
return null
|
|
86
100
|
}
|
|
87
|
-
val
|
|
88
|
-
|
|
101
|
+
val listed = o.optJSONArray("publicKeys")
|
|
102
|
+
val encoded = if (listed != null) List(listed.length()) { listed.optString(it) } else listOfNotNull(o.optString("publicKey").ifEmpty { null })
|
|
103
|
+
val raw = try {
|
|
104
|
+
encoded.map { Base64.decode(it, Base64.DEFAULT) }
|
|
89
105
|
} catch (e: IllegalArgumentException) {
|
|
90
106
|
return null
|
|
91
107
|
}
|
|
92
|
-
if (
|
|
108
|
+
if (raw.isEmpty() || raw.any { it.size != 32 } || o.optString("url").isEmpty() || o.optString("nativeApi").isEmpty()) return null
|
|
93
109
|
return AkanNativeUpdateConfig(
|
|
94
110
|
app = o.optString("app"),
|
|
111
|
+
version = o.optString("version"),
|
|
95
112
|
platform = o.optString("platform", "android"),
|
|
96
113
|
nativeApi = o.optString("nativeApi"),
|
|
97
114
|
embeddedSequence = o.optDouble("embeddedSequence", 0.0),
|
|
98
115
|
url = o.optString("url"),
|
|
99
|
-
|
|
116
|
+
keys = raw.map { AkanNativeKernel.updateKeyId(it) to it },
|
|
100
117
|
channel = o.optString("channel", "production"),
|
|
101
118
|
readyTimeoutMs = o.optLong("readyTimeout", 10_000),
|
|
102
119
|
dev = o.optBoolean("dev"),
|
|
120
|
+
reportUrl = o.optString("reportUrl").ifEmpty { null },
|
|
103
121
|
)
|
|
104
122
|
}
|
|
105
123
|
}
|
|
106
124
|
}
|
|
107
125
|
|
|
126
|
+
/** A `<channel>/<nativeApi>.json` envelope, checked as far as its signature: what the manifest says is read after. */
|
|
127
|
+
class AkanNativeUpdateEnvelope(val manifest: ByteArray, val keyId: String) {
|
|
128
|
+
companion object {
|
|
129
|
+
/** null: not an envelope, or signed by a key this binary does not trust or has revoked. */
|
|
130
|
+
fun open(data: ByteArray, config: AkanNativeUpdateConfig, revoked: List<String>): AkanNativeUpdateEnvelope? = try {
|
|
131
|
+
val o = JSONObject(String(data))
|
|
132
|
+
val keyId = o.getString("keyId")
|
|
133
|
+
val key = config.key(keyId)
|
|
134
|
+
val manifest = Base64.decode(o.getString("manifest"), Base64.DEFAULT)
|
|
135
|
+
val signature = Base64.decode(o.getString("signature"), Base64.DEFAULT)
|
|
136
|
+
if (!AkanNativeKernel.isUpdateKeyId(keyId) || keyId in revoked || key == null || manifest.size > (1 shl 20) ||
|
|
137
|
+
!AkanNativeUpdates.signed(manifest, signature, key)) null
|
|
138
|
+
else AkanNativeUpdateEnvelope(manifest, keyId)
|
|
139
|
+
} catch (e: Exception) {
|
|
140
|
+
null
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
108
145
|
object AkanNativeUpdates {
|
|
109
146
|
private const val TAG = "AkanNativeUpdates"
|
|
110
147
|
|
|
111
148
|
var config: AkanNativeUpdateConfig? = null
|
|
112
149
|
private set
|
|
113
|
-
|
|
150
|
+
internal lateinit var directory: File
|
|
151
|
+
private set
|
|
114
152
|
|
|
115
153
|
/** The bundle served in this session (null: the one inside the APK). */
|
|
116
154
|
var active: AkanNativeUpdateEntry? = null
|
|
@@ -150,16 +188,15 @@ object AkanNativeUpdates {
|
|
|
150
188
|
}
|
|
151
189
|
|
|
152
190
|
/**
|
|
153
|
-
* The bundle's
|
|
191
|
+
* The bundle's envelope (kept next to it by the plugin) verifies, describes this entry,
|
|
154
192
|
* and every file it lists is there with its size. The hashes were checked at the download.
|
|
155
193
|
*/
|
|
156
|
-
private fun verified(entry: AkanNativeUpdateEntry, config: AkanNativeUpdateConfig): Boolean {
|
|
194
|
+
private fun verified(entry: AkanNativeUpdateEntry, config: AkanNativeUpdateConfig, revoked: List<String>): Boolean {
|
|
157
195
|
val dir = bundleDirectory(entry.bundle)
|
|
158
196
|
return try {
|
|
159
|
-
val
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
val o = JSONObject(String(manifest))
|
|
197
|
+
val envelope = AkanNativeUpdateEnvelope.open(File(dir, "manifest.signed.json").readBytes(), config, revoked) ?: return false
|
|
198
|
+
if (envelope.keyId != entry.keyId) return false
|
|
199
|
+
val o = JSONObject(String(envelope.manifest))
|
|
163
200
|
val files = o.getJSONArray("files")
|
|
164
201
|
o.optString("bundle") == entry.bundle && o.optDouble("sequence") == entry.sequence && o.optString("nativeApi") == entry.nativeApi &&
|
|
165
202
|
o.optString("app") == config.app && o.optString("platform") == config.platform &&
|
|
@@ -207,23 +244,42 @@ object AkanNativeUpdates {
|
|
|
207
244
|
}
|
|
208
245
|
}
|
|
209
246
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
247
|
+
/** Whether a bundle may run in this binary: one it still takes, whose files are intact. */
|
|
248
|
+
fun usable(entry: AkanNativeUpdateEntry?, config: AkanNativeUpdateConfig, revoked: List<String>): Boolean =
|
|
249
|
+
entry != null && takes(entry, config, revoked) && intact(entry, config, revoked)
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Built for this native API, newer than the APK's own bundle, and signed by a key it trusts and has not revoked: a
|
|
253
|
+
* bundle a new binary or a revocation left behind is dropped as expected, not reported as a failure.
|
|
254
|
+
*/
|
|
255
|
+
private fun takes(entry: AkanNativeUpdateEntry, config: AkanNativeUpdateConfig, revoked: List<String>): Boolean =
|
|
256
|
+
entry.nativeApi == config.nativeApi && entry.sequence > config.embeddedSequence && entry.keyId in config.ring && entry.keyId !in revoked
|
|
257
|
+
|
|
258
|
+
private fun intact(entry: AkanNativeUpdateEntry, config: AkanNativeUpdateConfig, revoked: List<String>): Boolean =
|
|
259
|
+
File(bundleDirectory(entry.bundle), "index.html").isFile && verified(entry, config, revoked)
|
|
260
|
+
|
|
261
|
+
/** Drops an entry this launch cannot serve, reporting [event] (reason verify) when its files were the reason. */
|
|
262
|
+
private fun drop(entry: AkanNativeUpdateEntry?, config: AkanNativeUpdateConfig, revoked: List<String>, event: String): AkanNativeUpdateEntry? {
|
|
263
|
+
if (entry == null || !takes(entry, config, revoked)) return null
|
|
264
|
+
if (intact(entry, config, revoked)) return entry
|
|
265
|
+
AkanNativeUpdateReports.record(event, entry, "verify")
|
|
266
|
+
return null
|
|
267
|
+
}
|
|
213
268
|
|
|
214
269
|
/** Picks the bundle for this launch; returns its folder, or null for the APK's own bundle. */
|
|
215
270
|
fun launch(): File? {
|
|
216
271
|
val config = config ?: return null
|
|
217
272
|
val state = readState()
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
273
|
+
state.current = drop(state.current, config, state.revokedKeys, "rolledBack")
|
|
274
|
+
state.pending = drop(state.pending, config, state.revokedKeys, "failed")
|
|
275
|
+
state.trial = drop(state.trial, config, state.revokedKeys, "rolledBack")
|
|
221
276
|
state.trial?.let {
|
|
222
277
|
// Launched again without notifyReady(): the trial crashed or hung.
|
|
223
278
|
state.failed.add(it.bundle)
|
|
224
279
|
state.rolledBack = it.bundle
|
|
225
280
|
state.trial = null
|
|
226
281
|
Log.w(TAG, "bundle ${it.bundle} did not confirm; rolled back")
|
|
282
|
+
AkanNativeUpdateReports.record("rolledBack", it, "relaunch")
|
|
227
283
|
}
|
|
228
284
|
state.pending?.let {
|
|
229
285
|
if (!state.failed.contains(it.bundle)) {
|
|
@@ -233,6 +289,7 @@ object AkanNativeUpdates {
|
|
|
233
289
|
}
|
|
234
290
|
// Not on record: the pending bundle waits for a launch that can record it.
|
|
235
291
|
if (!writeState(state)) state.trial = null
|
|
292
|
+
state.trial?.let { AkanNativeUpdateReports.record("applied", it) }
|
|
236
293
|
active = state.trial ?: state.current
|
|
237
294
|
onTrial = state.trial != null
|
|
238
295
|
return active?.let { bundleDirectory(it.bundle) }
|
|
@@ -243,19 +300,20 @@ object AkanNativeUpdates {
|
|
|
243
300
|
val state = readState()
|
|
244
301
|
state.pending = entry
|
|
245
302
|
state.failed.remove(entry.bundle)
|
|
246
|
-
writeState(state)
|
|
303
|
+
if (writeState(state)) AkanNativeUpdateReports.record("downloaded", entry)
|
|
247
304
|
}
|
|
248
305
|
|
|
249
306
|
/** apply(): makes the pending bundle the trial now; returns its folder for the reload. */
|
|
250
307
|
fun applyPending(): File? {
|
|
251
308
|
val config = config ?: return null
|
|
252
309
|
val state = readState()
|
|
253
|
-
val pending = state.pending?.takeIf { usable(it, config) } ?: return null
|
|
310
|
+
val pending = state.pending?.takeIf { usable(it, config, state.revokedKeys) } ?: return null
|
|
254
311
|
state.trial = pending.copy(attempts = 1)
|
|
255
312
|
state.pending = null
|
|
256
313
|
if (!writeState(state)) return null
|
|
257
314
|
active = pending
|
|
258
315
|
onTrial = true
|
|
316
|
+
AkanNativeUpdateReports.record("applied", pending)
|
|
259
317
|
return bundleDirectory(pending.bundle)
|
|
260
318
|
}
|
|
261
319
|
|
|
@@ -270,13 +328,17 @@ object AkanNativeUpdates {
|
|
|
270
328
|
state.rolledBack = null
|
|
271
329
|
writeState(state)
|
|
272
330
|
onTrial = false
|
|
331
|
+
AkanNativeUpdateReports.record("confirmed", trial)
|
|
273
332
|
prune(listOfNotNull(state.current?.bundle, state.pending?.bundle))
|
|
274
333
|
}
|
|
275
334
|
|
|
276
|
-
/**
|
|
277
|
-
|
|
335
|
+
/**
|
|
336
|
+
* The trial did not confirm in time: back to the previous bundle. Returns its folder (null: the APK's own) and the
|
|
337
|
+
* trial it ended, whose report waits for the renderer probe to say whether the page timed out or hung.
|
|
338
|
+
*/
|
|
339
|
+
fun rollback(): Pair<File?, AkanNativeUpdateEntry?> {
|
|
278
340
|
val trial = active
|
|
279
|
-
if (!onTrial || trial == null) return active?.let { bundleDirectory(it.bundle) }
|
|
341
|
+
if (!onTrial || trial == null) return active?.let { bundleDirectory(it.bundle) } to null
|
|
280
342
|
val state = readState()
|
|
281
343
|
state.trial = null
|
|
282
344
|
state.failed.add(trial.bundle)
|
|
@@ -284,17 +346,27 @@ object AkanNativeUpdates {
|
|
|
284
346
|
writeState(state)
|
|
285
347
|
onTrial = false
|
|
286
348
|
val config = config
|
|
287
|
-
active = if (config != null && usable(state.current, config)) state.current else null
|
|
349
|
+
active = if (config != null && usable(state.current, config, state.revokedKeys)) state.current else null
|
|
288
350
|
Log.w(TAG, "bundle ${trial.bundle} did not call notifyReady() in time; rolled back")
|
|
289
|
-
return active?.let { bundleDirectory(it.bundle) }
|
|
351
|
+
return active?.let { bundleDirectory(it.bundle) } to trial
|
|
290
352
|
}
|
|
291
353
|
|
|
292
|
-
/** reset(): the APK's own bundle from the next launch on. */
|
|
354
|
+
/** reset(): the APK's own bundle from the next launch on. Revocations stay. */
|
|
293
355
|
fun reset() {
|
|
294
|
-
writeState(AkanNativeUpdateState())
|
|
356
|
+
writeState(AkanNativeUpdateState(revokedKeys = readState().revokedKeys))
|
|
295
357
|
prune(listOfNotNull(active?.bundle))
|
|
296
358
|
}
|
|
297
359
|
|
|
360
|
+
/** Keys a verified manifest revoked: no bundle they signed is served again, from the next launch on. */
|
|
361
|
+
fun revoke(keyIds: List<String>) {
|
|
362
|
+
val state = readState()
|
|
363
|
+
val added = keyIds.filter { it !in state.revokedKeys }
|
|
364
|
+
if (added.isEmpty()) return
|
|
365
|
+
state.revokedKeys.addAll(added)
|
|
366
|
+
writeState(state)
|
|
367
|
+
Log.w(TAG, "revoked keys ${added.joinToString(", ")}")
|
|
368
|
+
}
|
|
369
|
+
|
|
298
370
|
/** A download in progress (bundles/<bundle>.partial) is the plugin's, which removes it. */
|
|
299
371
|
private fun prune(keep: List<String>) {
|
|
300
372
|
val folder = File(directory, "bundles")
|
|
@@ -121,6 +121,26 @@ object AkanNativeVectors {
|
|
|
121
121
|
check(AkanNativeEd25519.verify(bytes(c[1] as String), bytes(c[2] as String), bytes(c[0] as String)) == c[3]) { "ed25519 ${c[4]}" }
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
// Updates protocol v2 (AkanNativeUpdates, AkanNativeKernel.updateDecision).
|
|
125
|
+
val updates = load("updates")
|
|
126
|
+
for (c in rows(updates, "keyIds")) {
|
|
127
|
+
val key = java.util.Base64.getDecoder().decode(c[0] as String)
|
|
128
|
+
check(AkanNativeKernel.updateKeyId(key) == c[1]) { "update keyId ${c[0]}" }
|
|
129
|
+
}
|
|
130
|
+
for (c in rows(updates, "decisions")) {
|
|
131
|
+
fun strings(v: Any?) = (v as List<*>).map { it as String }
|
|
132
|
+
val running = (c[7] as List<*>?)?.let { (it[0] as Number).toDouble() to it[1] as String }
|
|
133
|
+
val got = AkanNativeKernel.updateDecision(
|
|
134
|
+
strings(c[0]), strings(c[1]), c[2] as String, strings(c[3]), c[4] as Boolean,
|
|
135
|
+
(c[5] as Number).toDouble(), (c[6] as Number).toDouble(), running,
|
|
136
|
+
)
|
|
137
|
+
check(got.wire == c[8]) { "update decision ${c[9]}: ${got.wire}" }
|
|
138
|
+
}
|
|
139
|
+
for (c in rows(updates, "urls")) {
|
|
140
|
+
val got = AkanNativeKernel.updateManifestUrl(c[0] as String, c[1] as String, c[2] as String, c[3] as String)
|
|
141
|
+
check(got == c[4]) { "update url $got" }
|
|
142
|
+
}
|
|
143
|
+
|
|
124
144
|
// A missing or truncated file must not pass as fewer checks.
|
|
125
145
|
for ((name, count) in AkanNativeVectorData.counts) if ((ran[name] ?: 0) != count) failures.add("$name: ${ran[name] ?: 0} of $count checks ran")
|
|
126
146
|
if (AkanNativeVectorData.counts.isEmpty()) failures.add("no vectors in this build")
|
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
# It is not intended for manual editing.
|
|
3
3
|
version = 4
|
|
4
4
|
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "akan_native_desktop"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"block2",
|
|
10
|
+
"gtk",
|
|
11
|
+
"objc2",
|
|
12
|
+
"objc2-app-kit",
|
|
13
|
+
"objc2-foundation",
|
|
14
|
+
"tao",
|
|
15
|
+
"webkit2gtk",
|
|
16
|
+
"webview2-com",
|
|
17
|
+
"windows",
|
|
18
|
+
"wry",
|
|
19
|
+
]
|
|
20
|
+
|
|
5
21
|
[[package]]
|
|
6
22
|
name = "atk"
|
|
7
23
|
version = "0.18.2"
|
|
@@ -1310,22 +1326,6 @@ dependencies = [
|
|
|
1310
1326
|
"objc2-foundation",
|
|
1311
1327
|
]
|
|
1312
1328
|
|
|
1313
|
-
[[package]]
|
|
1314
|
-
name = "akan_native_desktop"
|
|
1315
|
-
version = "0.1.0"
|
|
1316
|
-
dependencies = [
|
|
1317
|
-
"block2",
|
|
1318
|
-
"gtk",
|
|
1319
|
-
"objc2",
|
|
1320
|
-
"objc2-app-kit",
|
|
1321
|
-
"objc2-foundation",
|
|
1322
|
-
"tao",
|
|
1323
|
-
"webkit2gtk",
|
|
1324
|
-
"webview2-com",
|
|
1325
|
-
"windows",
|
|
1326
|
-
"wry",
|
|
1327
|
-
]
|
|
1328
|
-
|
|
1329
1329
|
[[package]]
|
|
1330
1330
|
name = "once_cell"
|
|
1331
1331
|
version = "1.21.4"
|